Browse Source

update

master
zsmj 2 years ago
parent
commit
2733103687
  1. 13
      README.md
  2. BIN
      images/51.png
  3. BIN
      images/52.png
  4. BIN
      images/53.png
  5. BIN
      images/54.png
  6. BIN
      images/55.png
  7. 140
      questions/12.如何灵活应用布局组件,尽可能的减少DOM数量.md
  8. 96
      questions/13.每个布局组件都对应一个DOM节点吗.md
  9. 21
      questions/27.effect的妙用.md
  10. 83
      questions/35.不用resize实现拖动调整宽高布局.md
  11. 2
      questions/38.绑定listeners时候this的新写法.md
  12. 99
      questions/39.利用bi.loader快速封装分页加载更多列表.md

13
README.md

@ -25,7 +25,7 @@ FineUI 100个问题题,带你走进FineUI的世界
- [9、z-index解析以及在FineUI中使用原则](./questions/9.z-index解析以及在FineUI中使用原则.md)
- [10、computed通俗易懂的原理解析和日常排错](./questions/1.如何获取当前时间.md)
- [11、绝对布局的隐藏知识点](./questions/41.绝对布局的隐藏知识点.md)
- [12、如何灵活应用布局组件,尽可能的减少DOM数量?]()
- [12、如何灵活应用布局组件,尽可能的减少DOM数量?](./questions/12.如何灵活应用布局组件,尽可能的减少DOM数量.md)
- [13、何时会滚动,滚动条位置如何贴边,究竟是怎么回事](./questions/42.何时会滚动,滚动条位置如何贴边,究竟是怎么回事.md)
- [14、如何监听元素大小变化](./questions/20.如何监听元素大小变化.md)
- [15、阻止冒泡在FineUI中适用场景](./questions/15.阻止冒泡在FineUI中适用场景.md)
@ -44,7 +44,7 @@ FineUI 100个问题题,带你走进FineUI的世界
- [10、Fix.set和Fix.del是为了解决什么问题?](./questions/10.Fix.set和Fix.del是为了解决什么问题.md)
- [11、Fix中对数组、对象的操作技巧](./questions/11.Fix中对数组、对象的操作技巧.md)
- [12、computed进行列表组件的状态控制](./questions/21.computed%E8%BF%9B%E8%A1%8C%E5%88%97%E8%A1%A8%E7%BB%84%E4%BB%B6%E7%9A%84%E7%8A%B6%E6%80%81%E6%8E%A7%E5%88%B6.md)
- [13、如何在开发中有效减少dom数量]()
- [13、每个布局组件都对应一个DOM节点吗?](./questions/13.每个布局组件都对应一个DOM节点吗.md)
- [14、怎么实现一个树形控件]()
- [15、disabled的父子控制]()
- [16、为什么不推荐使用同步的watch]()
@ -58,7 +58,7 @@ FineUI 100个问题题,带你走进FineUI的世界
- [24、选中、hover样式的通用处理规则](./questions/26.tab选项卡组件的logic属性实现动态高度.md)
- [25、如何独立控制组件文字和图标颜色](./questions/34.独立控制组件文字和图标颜色.md)
- [26、文件上传控件多次选择文件和自定义校验](./questions/35.文件上传控件多次选择文件和自定义校验.md)
- [27、effect的妙用]()
- [27、effect的妙用](27.effect的妙用.md)
- [28、defer和nextTick有什么区别]()
- [29、为什么说随意修改原始数据时万恶之源?]()
- [30、空状态提示的若干种实现方式]()
@ -66,10 +66,11 @@ FineUI 100个问题题,带你走进FineUI的世界
- [32、有没有一种布局方式,在文本保持垂直居中的情况下,文本很多时,可以限制其不超出外层高度 并出现滚动条](./questions/32.有没有一种布局方式,在文本保持垂直居中的情况下,文本很多时,可以限制其不超出外层高度 并出现滚动条.md)
- [33、如何快速的封装自定义combo](./questions/33.如何快速的封装自定义combo.md)
- [34、horizontalAlign:stretch是怎么一回事儿]()
- [35、不用resize实现拖动调整宽高布局]()
- [35、不用resize实现拖动调整宽高布局](./questions/35.不用resize实现拖动调整宽高布局.md)
- [36、reset方法的滥用]()
- [37、hover-visible的原理及使用方式.md](./questions/37.hover-visible的原理及使用方式.md)
- [38、绑定listeners时候this的新写法.md](./questions/38.绑定listeners时候this的新写法.md)
- [37、hover-visible的原理及使用方式](./questions/37.hover-visible的原理及使用方式.md)
- [38、绑定listeners时候this的新写法](./questions/38.绑定listeners时候this的新写法.md)
- [39、利用bi.loader快速封装分页加载更多列表](./questions/39.利用bi.loader快速封装分页加载更多列表.md)
### 代码之外

BIN
images/51.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
images/52.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

BIN
images/53.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
images/54.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
images/55.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

140
questions/12.如何灵活应用布局组件,尽可能的减少DOM数量.md

@ -0,0 +1,140 @@
# 如何灵活应用布局组件,尽可能的减少DOM数量
众所周知,DOM数量越多,前端越卡.很多前端者开发者绞尽脑汁,使出浑身解数,就是为了减少dom数量,提升页面性能
列举一些常见的增加DOM数量的写法以及优化方案
## 列表节点的层级偏移
![示例1](../images/51.png)
```javascript
const render = () => {
const layer = this.options.layer; // 表示节点层级
const items = [];
for (let i = 0; i <= layer; i++) {
items.push({
type: "bi.layout",
width: 12
});
}
items.push({
type: "bi.label",
text: "节点"
});
items.push({
type: "bi.icon_button",
title: "按钮"
});
return {
type: "bi.horizontal_adapt",
items,
};
};
```
这种场景,如果每个层级都需要用一个空的div占据空间,随着树的层级加深,dom数大大增加
常用解决方案,通过布局`lgap`实现,注意利用el的隔离特性,不要让`lgap`影响到item
有兴趣的可以参考一下FineUI树控件的迭代过程,如何减少DOM
```javascript
const render = () => {
const layer = this.options.layer; // 表示节点层级
const items = [];
for (let i = 0; i <= layer; i++) {
items.push({
type: "bi.layout",
width: 12
});
}
return {
type: "bi.horizontal_adapt",
items: [
{
el: {
type: "bi.label",
text: "节点"
},
lgap: layer * 12,
}, {
type: "bi.icon_button",
title: "按钮"
}
]
};
};
```
## 垂直流布局的卡片间隔
![示例2](../images/52.png)
数值排列的卡片,灰色的间隔,常见的错误是通过DOM来实现分割条
```javascript
const render = () => {
return {
type: "bi.vertical",
items: [
{
el: {
type: "bi.label",
cls: "bi-card",
text: "card1"
},
}, {
type: "bi.layout",
cls: "bi-background",
height: 10,
}, {
el: {
type: "bi.label",
cls: "bi-card",
text: "card2"
},
},
]
};
};
```
如上写法每多一个卡片,都需要一个额外的空DOM
应对这种场景,我们可以给容器统一设置`bi-background`灰色背景,然后对每一个卡片添加`bi-card`样式, 间隔用`bgap`实现.
```javascript
const render = () => {
return {
type: "bi.vertical",
cls: "bi-background",
items: [
{
el: {
type: "bi.label",
cls: "bi-card",
text: "card1"
},
bgap: 10,
}, {
el: {
type: "bi.label",
cls: "bi-card",
text: "card2"
},
},
]
};
};
```

96
questions/13.每个布局组件都对应一个DOM节点吗.md

@ -0,0 +1,96 @@
# 每个布局组件都对应一个DOM节点吗
答案显然是否定的,那么有没有仔细探究一下,哪些场景不是对应一个DOM呢?
举个例子: 如下布局有什么问题?
```javascript
const render = () => {
return [
{
el: {
type: "bi.vertical",
items: [
{
type: "bi.label",
cls: "bi-card",
text: "card1"
}
]
},
}, {
type: "bi.absolute",
invisible: () => !this.model.tipVisible,
items: [
{
el: {
type: "bi.icon_label",
title: "tip"
},
right: 0, top: 0
}
]
}
];
};
```
![示例](../images/54.png)
观察DOM结构可以发现,`bi.vertical`和`bi.absolute`布局组件共享了一个DOM,且最终布局效果不会产生相互影响.
但是共享一个DOM需要额外注意一点,设置invisible属性时候需要知晓副作用.
如上示例,`bi.absolute`布局 invisible为true的时候,`bi.vertical`也会消失不见.
原因也很简单: invisible是通过对DOM设置`display:none`样式,自然导致了这种结果. 解决方式也很简单,将invisible控制放到`bi.absolute`组件内部元素
另一个示例,web组件中常用的`bi.iframe`组件
如下示例: iframe可以正常渲染吗?
```javascript
class IframeWidget extends BI.Widget {
props = {
baseCls: "test-frame"
};
render() {
return {
type: "bi.iframe",
src: "http://www.bing.com"
};
}
}
```
![示例](../images/55.png)
答案是不行的,这是为什么呢?这是因为`bi.iframe`组件和当前IframeWidget组件共用一个DOM,父组件控制的node类型为div,覆盖掉了`bi.iframe`设定的iframe类型
同理bi.image组件也有类似场景
解决这类问题也很容易,给`bi.iframe`一个专用的DOM即可
```javascript
class IframeWidget extends BI.Widget {
props = {
baseCls: "test-frame"
};
render() {
return {
type: "bi.adaptive",
items: [
{
type: "bi.iframe",
src: "http://www.bing.com",
height: "100%",
width: "100%",
}
]
};
}
}
```

21
questions/27.effect的妙用.md

@ -0,0 +1,21 @@
# effect的妙用
FineUI组件中text,value,cls,css,selected,items,columnSize,rowSize,invisible,disabled等属性都已经支持了响应式
但是,总有一些属性没有支持响应式,或者一些组件提供的props并未支持响应式,这时候只能回归`_store`+`watch`了吗?
非也,有effect属性
```javascript
const state = Fix.define({
state1: 0
});
const render = () => {
return {
type: "bi.my_custom_wdiget",
effect: (customWidget) => {
customWidget.customMethod(state.state1);
}
};
};
```

83
questions/35.不用resize实现拖动调整宽高布局.md

@ -0,0 +1,83 @@
# 不用resize实现拖动调整宽高布局
我们都知道,布局组件有个`resize`方法,以前常用的动态宽度或高度的实现方式大多借用了该方法
例如可拖动宽度的布局
```javascript
class Resizeable extends BI.Widget {
props = {
baseCls: "test"
};
render() {
return {
type: "bi.htape",
ref: ref => this.container = ref,
items: [
{
type: "bi.draggabel", // 假设为拖拽组件
text: "left",
width: 100,
onDragg: size => this.resize(size),
}, {
type: "bi.label",
text: "right"
}
]
};
}
resize(size) {
this.container.attr("items")[0].width = size;
this.container.resize();
}
}
```
多数时候我们将拖动组件绑定在左侧组件上,此时需要监听拖动回调,然后修改容器的items属性,最后调用resize
有没有更简便的方式呢?有的
FineUI3.0 版本新增的自适应布局,充分利用了flex布局特性,为我们提供了更便捷,更内聚的实现方式
```javascript
class Draggable extends BI.Widget {
props = {
baseCls: "test"
};
render() {
return {
type: "bi.draggabel", // 假设为拖拽组件
text: "left",
onDragg: size => this.element.width(size),
};
}
}
class Resizeable extends BI.Widget {
props = {
baseCls: "test"
};
render() {
return {
type: "bi.horizontal",
verticalAlign: "stretch",
columnSize: ["", "fill"],
items: [
{
type: Draggable.xtype,
text: "left",
}, {
type: "bi.label",
text: "right"
}
]
};
}
}
```
利用水平布局自适应的实现方式,左侧为实际宽度,右侧占满剩余宽度. 这时候左侧仅需关注自身宽度,无须考虑与外部联动

2
questions/38.绑定listeners时候this的新写法.md

@ -34,4 +34,4 @@ class Widget extends BI.Widget {
}
```
相信大家能看出两个listner的区别
相信大家能看出两个listener的区别, 一个可以省掉self,但是需要ref,一个不需要self可以直接通过this访问组件

99
questions/39.利用bi.loader快速封装分页加载更多列表.md

@ -0,0 +1,99 @@
# 利用bi.loader快速封装分页加载更多列表
长列表,从后端分页加载,搜索也由后端处理. 非常常见的需求
用过ButtonGroup的都知道格式化好items,然后直接populate就行了.
Loader也类似,只是他还具有itemsCreator的能力 [bi.loader](https://code.fineres.com/projects/VISUAL/repos/fineui/browse/src/base/combination/loader.js)
```javascript
class MyList extends BI.Widget {
hasNext = false;
render() {
return {
type: "bi.loader",
itemsCreator: (op, callback) => {
const times = op.times; // times标记分页码
setTimeout(() => {
callback(this.formatItems(/* some datas */));
});
},
hasNext: () => this.hasNext
};
}
formatItems(items) {
// 一般格式化节点常用的状态
let keyword;
let selected;
let disabled;
return items.map(item => {
return {
...item,
keyword,
selected,
disabled,
};
});
}
}
```
常见操作手法
### bi.loader依旧支持items属性,如果非空,会直接渲染出来作为第一页
### bi.loader可以直接调用空的populate方法,其会自动触发itemsCreator请求数据
利用这种机制可以将数据请求集中化. 无需在筛选条件变化之后,手动去请求来数据,然后再populate到Loader里面
```javascript
class MyList extends BI.Widget {
watch = {
"keyword | filter | perPage": () => {
this.loader.populate();
}
};
render() {
return {
type: "bi.loader",
ref: ref => this.loader = ref,
itemsCreator: (op, callback) => {
const times = op.times; // times标记分页码
requestItems(op.times, callback(/* some datas */));
},
};
}
requestItems(page, cb) {
// 一般常用的请求条件
let keyword;
let filter;
let perPage;
fetchData({
page,
keyword,
filter,
perPage,
}).then(cb);
}
}
```
### hasNext的处理怎么才能更优雅
查阅内部源码,hasNext可以利用count props,也可以由外部回调
这样就有两种操作姿势
1. 在itemsCreator回调的时候修改props`this.loader.attr("count",res.allCount)`
2. 在itemsCreator回调的时候保存状态,hasNext回调给loader `hasNext:() => this.hasNext`
孰优孰劣见仁见智,但有没有更符合开发直觉的方式呢? 例如 `callback({items,hasNext,count})`
Loading…
Cancel
Save