zsmj
2 years ago
4 changed files with 160 additions and 2 deletions
@ -0,0 +1,97 @@ |
|||||||
|
# 关于组件引用的奥秘,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: {}, |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
@ -0,0 +1,58 @@ |
|||||||
|
## 高阶组件的render props.md |
||||||
|
|
||||||
|
在FineUI中,我们经常见到一些继承抽象组件的写法,为了实现某种功能,继承抽象组件重新定义一个组件 |
||||||
|
|
||||||
|
依据我们的编码规范,一个组件一个文件,被迫新建众多文件 |
||||||
|
``` |
||||||
|
// 用于loading效果的组件 |
||||||
|
const Widget1 = BI.inherit(BI.Pane, { |
||||||
|
|
||||||
|
beforeRender: function () { |
||||||
|
this.loading(); |
||||||
|
}, |
||||||
|
|
||||||
|
}); |
||||||
|
|
||||||
|
// 用于封装可以点击的组件 |
||||||
|
const Widget2 = BI.inherit(BI.BasicButton, { |
||||||
|
|
||||||
|
render: function () { |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
}); |
||||||
|
|
||||||
|
// 用于封装带有tooltip功能的组件 |
||||||
|
const Widget3 = BI.inherit(BI.Single, { |
||||||
|
|
||||||
|
render: function () { |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
}); |
||||||
|
``` |
||||||
|
|
||||||
|
以BI.BasicButton举例,很多时候我们只是想快速创建一个可以点击的组件,此时可以借助render-props来实现 |
||||||
|
``` |
||||||
|
const MyButton = { |
||||||
|
type: "bi.basic_button", |
||||||
|
render: () => { |
||||||
|
return { |
||||||
|
type: "bi.vertical_adapt", |
||||||
|
items: [ |
||||||
|
{ |
||||||
|
type: "bi.label", |
||||||
|
text: "文字", |
||||||
|
}, { |
||||||
|
type: "bi.icon_button", |
||||||
|
cls: "delete-font", |
||||||
|
title: "删除按钮", |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
}, |
||||||
|
handler: () => { |
||||||
|
console.log("点击了"); |
||||||
|
}, |
||||||
|
}; |
||||||
|
``` |
Loading…
Reference in new issue