# 关于组件引用的奥秘,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: {}, }; } } ```