8 changed files with 198 additions and 5 deletions
After Width: | Height: | Size: 92 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 43 KiB |
@ -0,0 +1,19 @@ |
|||||||
|
# 隐藏与显示组件的冷门知识点 |
||||||
|
|
||||||
|
FineUI中组件`setVisible`方法采用的是`display:none`的形式隐藏组件. |
||||||
|
|
||||||
|
优点大家都知道,不占据DOM流之类的. |
||||||
|
|
||||||
|
但是缺点也很明显,多tab之类的组件,隐藏的元素无法获取宽高,这也是一些"组件缩成一坨"问题的直接原因 |
||||||
|
|
||||||
|
那么为什么不用`visibility:hidden`呢? |
||||||
|
|
||||||
|
其实有个原因是input元素`focus`的特性导致 |
||||||
|
|
||||||
|
采用`visibility:hidden`形式隐藏组件,为了避免鼠标事件触发等,大多会附加一个超大的`top,left`样式,或者`translateX()`超大值,将其挪到屏幕外面 |
||||||
|
|
||||||
|
然而`focus`操作默认有个scrollToView特性,其会不受限制的自动跳到屏幕中间 |
||||||
|
|
||||||
|
![示例](../images/58.png) |
||||||
|
|
||||||
|
例如决策平台的modern主题,开发者无法控制每个打开的tab里面是否会有代码逻辑触发`focus`,因此只能采用`display:none`的形式隐藏tab,否则就容易出现这种位置异常 |
@ -0,0 +1,12 @@ |
|||||||
|
# defer和nextTick有什么区别 |
||||||
|
|
||||||
|
研读FineUI代码时,会发现有的地方用了`BI.defer`,有的地方用了`BI.nextTick`,有什么区别呢? |
||||||
|
|
||||||
|
`BI.defer`源自lodash,官方描述是Defers invoking the func until the current call stack has cleared.,翻译一下就是在当前调用栈执行完毕之后调用. |
||||||
|
|
||||||
|
看起来很高大上实际上底层实现就是`settimeout(fn,0)` |
||||||
|
|
||||||
|
`BI.nextTick`的实现相对复杂,采用的是"能力检测"策略,优先使用`Promise.resolve()`,不支持的话使用`MutationObserver`,不支持的话`setImmediate`,还是不支持的话 |
||||||
|
那就只能`settimeout(fn,0)`了 |
||||||
|
|
||||||
|
由此可见,实际作用都是异步的延迟执行某段事务,使用`BI.nextTick`效率会更高一些 |
@ -0,0 +1,137 @@ |
|||||||
|
# 空状态提示的若干种实现方式 |
||||||
|
|
||||||
|
![示例](../images/59.png) |
||||||
|
|
||||||
|
## 布局实现 |
||||||
|
|
||||||
|
一般情况下,采用`bi.absolute`布局放置内容和空提示 |
||||||
|
|
||||||
|
```javascript |
||||||
|
const widget = { |
||||||
|
type: "bi.absolute", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
el: { |
||||||
|
type: "content", |
||||||
|
}, |
||||||
|
inset: 0 |
||||||
|
}, { |
||||||
|
el: { |
||||||
|
type: "empty_tip", |
||||||
|
invisible: () => !this.model.tipVisible |
||||||
|
}, |
||||||
|
inset: 0 |
||||||
|
} |
||||||
|
] |
||||||
|
}; |
||||||
|
``` |
||||||
|
|
||||||
|
## Layers实现 |
||||||
|
|
||||||
|
如果想脱离组件层面,以service的形式对组件施加空状态提示,也可以使用`BI.Layers`控制,实现对任意组件附加空提示 |
||||||
|
|
||||||
|
```javascript |
||||||
|
function createEmptyTyp(widget) { |
||||||
|
const name = BI.UUID(); |
||||||
|
BI.Layers.create(name, null, { |
||||||
|
container: widget, |
||||||
|
render: { |
||||||
|
type: "empty_tip", |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
BI.Layers.show(name); |
||||||
|
return () => { |
||||||
|
BI.Layers.remove(name); |
||||||
|
}; |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
## 状态控制 |
||||||
|
|
||||||
|
用独立清晰的状态控制空提示的显示隐藏,避免掺杂在其他状态控制中 |
||||||
|
|
||||||
|
如下示例,在items的watch中"顺带"处理tip组件显示隐藏,使得控制逻辑变的不够清晰 |
||||||
|
|
||||||
|
```javascript |
||||||
|
class model extends Model { |
||||||
|
state = { |
||||||
|
items: [] |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
class widget extends BI.Widget { |
||||||
|
watch = { |
||||||
|
items: (items) => { |
||||||
|
this.list.populate(items); |
||||||
|
this.tip.setVisible(BI.isEmpty(items)); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
render() { |
||||||
|
return { |
||||||
|
type: "bi.absolute", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
el: { |
||||||
|
type: "content", |
||||||
|
ref: ref => this.list = ref, |
||||||
|
}, |
||||||
|
inset: 0 |
||||||
|
}, { |
||||||
|
el: { |
||||||
|
type: "empty_tip", |
||||||
|
ref: ref => this.tip = ref, |
||||||
|
invisible: !BI.isEmpty(this.model.items) |
||||||
|
}, |
||||||
|
inset: 0 |
||||||
|
} |
||||||
|
] |
||||||
|
}; |
||||||
|
} |
||||||
|
}; |
||||||
|
``` |
||||||
|
将tip显示隐藏的状态独立出来,独立控制,这样状态到视图的映射清晰明了 |
||||||
|
|
||||||
|
```javascript |
||||||
|
class model extends Model { |
||||||
|
state = { |
||||||
|
items: [] |
||||||
|
}; |
||||||
|
|
||||||
|
computed = { |
||||||
|
tipVisible: () => BI.isEmpty(this.model.items) |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
class widget extends BI.Widget { |
||||||
|
watch = { |
||||||
|
items: (items) => { |
||||||
|
this.list.populate(items); |
||||||
|
}, |
||||||
|
tipVisible: b => this.tip.setVisible(b) |
||||||
|
}; |
||||||
|
|
||||||
|
render() { |
||||||
|
return { |
||||||
|
type: "bi.absolute", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
el: { |
||||||
|
type: "content", |
||||||
|
ref: ref => this.list = ref, |
||||||
|
}, |
||||||
|
inset: 0 |
||||||
|
}, { |
||||||
|
el: { |
||||||
|
type: "empty_tip", |
||||||
|
ref: ref => this.tip = ref, |
||||||
|
invisible: !this.model.tipVisible, |
||||||
|
}, |
||||||
|
inset: 0 |
||||||
|
} |
||||||
|
] |
||||||
|
}; |
||||||
|
} |
||||||
|
}; |
||||||
|
``` |
Loading…
Reference in new issue