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.
 

2.3 KiB

关于组件引用的奥秘,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的一些特性详解一文中强调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: {},
        };
    }
}