You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
2.3 KiB

2 years ago
# 关于组件引用的奥秘,ref知多少
类似于React和Vue获取DOM元素引用的形式FineUI中也可以获取组件实例的引用,有两种方式
1. BI.createWidget方法的返回值
2. 组件props中的ref属性(推荐)
## ref在什么时候调用
组件ref会在组件render之后回调`this.options.ref.call(this, this)`,同时也会在组件destoryed之后再次回调`this.options.ref.call(null, null)`
这也是为什么在[combo的一些特性详解](./80.combo的一些特性详解.md)一文中强调combo的popup是在弹出时候创建的,有时候虽然写了ref,但是暂时还拿不到.
## ref不是只回调一次哦
使用ref时推荐如下写法,使用参数
```
{
type: "bi.button",
text: "左上角",
ref: function (_ref) {
xxx = _ref;
},
}
```
不推荐用this赋值的写法,因为在组件destoryed之后的回调,this可能是window对象.
```
{
type: "bi.button",
text: "左上角",
ref: function () {
xxx = this;
},
}
```
## 用BI.createWidget有什么不好吗,什么时候可以用BI.createWidget呢
1. 相较于ref,BI.createWidget缺少相应的内存回收
2. BI.createWidget会破坏render()=>json 的清晰代码结构
3. 在封装高阶组件的时候,组件内部需要获取子组件引用,同时还有外部传入的props存在ref的场景.
例如如下示例,此时外部传入的ref失效了
```
class MyComponent extends BI.Widget {
static xtype = "my.component";
render() {
const el = this.options.el;
return {
type: "bi.combo",
el: {
...el,
ref: ref => {
this.trigger = ref;
},
},
popup: {},
};
}
}
let myRef;
const widget = {
type: MyComponent.xtype,
ref: ref => {
myRef = ref;
},
}; render:
}
```
如何避免这类错误呢,有两种可选方案,使用BI.createWidget方法,或者使用私有的__ref
```
class MyComponent extends BI.Widget {
static xtype = "my.component";
render() {
const el = this.options.el;
return {
type: "bi.combo",
el: {
...el,
__ref: ref => {
this.trigger = ref;
},
},
popup: {},
};
}
}
```