After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 163 KiB |
After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 125 KiB |
@ -0,0 +1,17 @@
|
||||
# 阻止冒泡在FineUI中适用场景 |
||||
|
||||
FineUI中Button,Combo等组件支持stopPropagation属性,顾名思义,作用是阻止冒泡的,那么具体哪些场景适用于阻止冒泡呢? |
||||
|
||||
![示例](../images/47.png) |
||||
|
||||
在外部组件可点击的情况下,内部包含独立可点击的组件 |
||||
|
||||
常见的自定义列表及树状节点,节点自身支持点击选中,同时节点的展开收起箭头以及右侧的更短选项图标按钮点击的时候不需要触发节点的选中. |
||||
这种情况下就轮到stopPropagation上场了. 例如阻止了展开收起箭头的冒泡,此时点击展开收起箭头只会触发树节点的展开收起,不会触发点击 |
||||
|
||||
阻止冒泡无须滥用,仅在明确意识到需要使用的时候方可使用. |
||||
|
||||
阻止冒泡会带来些许副作用,这些作为已知现象并不需要刻意解决 |
||||
|
||||
例如可以拖动的组件,拖动过程中,在stopPropagation的元素上松开鼠标,会导致拖动状态不能正常结束. |
||||
|
@ -0,0 +1,63 @@
|
||||
# 如何快速的封装自定义combo |
||||
|
||||
FineUI中提供了很多下拉框组件,但总有时候不满足使用场景,需要自己封装 |
||||
|
||||
那么如何快速封装一个combo组件呢?总结多年的经验,分如下几个步骤 |
||||
|
||||
## 1.确定好el和popup |
||||
|
||||
想好触发器和展开面板显示的内容.举个常见的例子,一个水平布局,包含一个文字和一个图标组成了el,一个button组成了面板 |
||||
|
||||
```javascript |
||||
const combo = { |
||||
type: "bi.combo", |
||||
el: { |
||||
type: "bi.horizontal_fill", |
||||
columnSize: ['fill', 24], |
||||
items: [ |
||||
{ |
||||
type: "bi.label", |
||||
text: "我是el" |
||||
}, { |
||||
type: "bi.icon_label", |
||||
text: "我是el上的图标" |
||||
} |
||||
] |
||||
}, |
||||
popup: { |
||||
el: { |
||||
type: "bi.button", |
||||
text: "请点击" |
||||
} |
||||
} |
||||
}; |
||||
``` |
||||
|
||||
## 2.确定好触发方式 |
||||
|
||||
根据交互需要,确定好需要点击触发,还是鼠标悬浮触发,选择一个合适的`trigger`属性 |
||||
|
||||
## 3.确定好收起面板的控制逻辑 |
||||
|
||||
多数时候,我们需要在弹出面板进行操作之后收起面板,这时候需要手动监听事件调用`hideView`方法 |
||||
|
||||
```javascript |
||||
let comboRef; |
||||
const combo = { |
||||
type: "bi.combo", |
||||
ref: ref => comboRef = ref, |
||||
popup: { |
||||
el: { |
||||
type: "bi.button", |
||||
text: "请点击", |
||||
handler: () => { |
||||
comboRef.hideView() |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
``` |
||||
|
||||
## 4.完善好设置值和获取值逻辑 |
||||
|
||||
在[combo特性详解中](./80.combo的一些特性详解.md)阐述了combo的特性,可以参考 |
@ -0,0 +1,34 @@
|
||||
# 文件上传控件多次选择文件和自定义校验 |
||||
|
||||
在使用FineUI中上传文件控件的时候,如果想要自定义文件校验规则怎么办呢? |
||||
|
||||
```javascript |
||||
const file = { |
||||
type: "bi.file", |
||||
multiple: true, |
||||
accept: ".png,.pdf,image/jpg,image/*", |
||||
maxSize: 1024 * 1024, // 最大文件大小 |
||||
maxLength: 3, // 最大文件个数 |
||||
errorText: function (error) { |
||||
return "上传失败啦"; |
||||
}, |
||||
listeners: [{ |
||||
eventName: "EVENT_CHANGE", |
||||
action: function (obj) { |
||||
// 可以对文件进行处理及判断 |
||||
const files = obj.files; |
||||
const invalid = files.some(file => { |
||||
if (/image/.test(file.type) && file.size > 1024 * 10) { |
||||
BI.Msg.toast(`${file.type}类型文件不允许超过10KB`, { level: "error" }); |
||||
return true; |
||||
} |
||||
}); |
||||
// 可选的是否清空掉上次上传的内容 |
||||
file.reset(); |
||||
!invalid && file.upload(); |
||||
} |
||||
}] |
||||
}; |
||||
``` |
||||
|
||||
file组件在选择文件后,会触发`EVENT_CHANGE`事件,对外抛出的参数包含所选文件列表,我们可以对这些内容进行筛选处理,进行自定义校验等操作 |
@ -0,0 +1,96 @@
|
||||
# hover-visible的原理及使用方式 |
||||
|
||||
常见的交互场景,某个元素在一般情况下隐藏,当鼠标悬浮到父元素上之后,该元素显示 |
||||
|
||||
![示例](../images/48.gif) |
||||
|
||||
FineUI中提供了两种方式实现这种效果,分开举例 |
||||
|
||||
# less .hover-visible() mixin |
||||
|
||||
## 源码分析 |
||||
|
||||
利用less强大的混合功能,默认状态`visibility:hidden`,在父级容器hover时状态变成`visibility:visible` |
||||
|
||||
```less |
||||
.hover-visible(@cls) { |
||||
& .@{cls} { |
||||
visibility: hidden; |
||||
} |
||||
&:hover { |
||||
& .@{cls} { |
||||
visibility: visible; |
||||
} |
||||
} |
||||
} |
||||
``` |
||||
|
||||
## 应用示例 |
||||
|
||||
在编写less代码时,只需要在对应父级class下面加入`.hover-visible()`mixin即可 |
||||
|
||||
```less |
||||
.my-demo { |
||||
.hover-visible(add-button); |
||||
} |
||||
``` |
||||
|
||||
编译为css |
||||
```css |
||||
.my-demo .add-button { |
||||
visibility: hidden; |
||||
} |
||||
.my-demo:hover .add-button { |
||||
visibility: visible; |
||||
} |
||||
``` |
||||
|
||||
## .hover-visible有什么缺陷吗? |
||||
|
||||
众所周知,`visibility:hidden`仅仅隐藏了元素,但依旧占据文档流位置的,入下图所示,这样白白浪费了节点右侧可以利用的空间,体验不好. |
||||
|
||||
![示例](../images/46.png) |
||||
|
||||
为了应对这种非常常见的场景,FineUI提供了一套样式方案: |
||||
|
||||
# .hover-visible-container .hover-visible-item |
||||
|
||||
兄弟搭配,其力断金.一套class类名组合,提升编码效率. |
||||
|
||||
## 源码分析 |
||||
|
||||
首先,基于`visibility:hidden`的不足,我们期望元素隐藏时能够`display:none`,父级元素hover时正常显示出来. |
||||
|
||||
借助css3 `:where`和`:not`伪类,我们巧妙的实现了这一功能 |
||||
|
||||
```less |
||||
.bi-hover-visible-container { |
||||
|
||||
& .bi-hover-visible-item { |
||||
visibility: hidden; |
||||
} |
||||
|
||||
&:hover .bi-hover-visible-item { |
||||
visibility: visible; |
||||
} |
||||
|
||||
&:where(:not(&:hover)) .bi-hover-visible-item { |
||||
display: none; |
||||
} |
||||
} |
||||
``` |
||||
|
||||
用通俗语音解释,前两天规则很容易理解:默认状态`bi-hover-visible-item`隐藏,父节点hover时`bi-hover-visible-item`显示 |
||||
最后一条是什么含义呢? |
||||
当父节点`bi-hover-visible-container`没被hover的时候,子节点`bi-hover-visible-item`的样式为`display: none` |
||||
|
||||
这样一来,是不是完美了,正常状态被隐藏的元素不占据dom空间,当hover的时候,由于失去了`display: none`规则,那么其恢复成了原始的状态,`display:block`或`display:flex`,重新占据文档流 |
||||
|
||||
![示例](../images/49.gif) |
||||
|
||||
## IE浏览器上需要注意的点 |
||||
|
||||
由于IE浏览器不支持`:where`和`:not`,因此在IE上始终占据空间 |
||||
其次对于使用`bi-hover-visible-container`和`bi-hover-visible-item`组合类名的形式,在IE上不能嵌套使用. |
||||
`.bi-hover-visible-container` > `.bi-hover-visible-item` > `.bi-hover-visible-container` > `.bi-hover-visible-item` 的组合是不行的 |
||||
对于这种场景,可以采用原始的less方法`.hover-visible()`处理 |
@ -0,0 +1,2 @@
|
||||
# combo的popup是异步组件的情况下会有哪些问题 |
||||
|
@ -0,0 +1,37 @@
|
||||
# 绑定listeners时候this的新写法 |
||||
|
||||
FineUI中事件体系,借用listeners进行事件通知. |
||||
在绑定事件的时候,有的同学喜欢使用箭头函数,有的同学喜欢使用传统function() |
||||
并无优劣,唯一需要注意的即是this指向问题 |
||||
|
||||
先看一个示例 |
||||
|
||||
```javascript |
||||
class Widget extends BI.Widget { |
||||
|
||||
render() { |
||||
const self = this; |
||||
|
||||
const widget = { |
||||
type: "bi.multi_select_item", |
||||
ref: ref => this.itemRef = ref, |
||||
text: "复选item", |
||||
listeners: [ |
||||
{ |
||||
eventName: BI.MultiSelectItem.EVENT_CHANGE, |
||||
actin: () => { |
||||
this.fireEvent("EVENT_CHANGE", this.itemRef.isSelected()) |
||||
} |
||||
}, { |
||||
eventName: BI.MultiSelectItem.EVENT_CHANGE, |
||||
actin: function () { |
||||
self.fireEvent("EVENT_CHANGE", this.isSelected()) |
||||
} |
||||
} |
||||
] |
||||
} |
||||
} |
||||
} |
||||
``` |
||||
|
||||
相信大家能看出两个listner的区别 |