diff --git a/README.md b/README.md index e056b9f..0f4c17d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # FineUI-100-Questions -FineUI入门100题,带你走进FineUI的世界 +FineUI 100个问题题,带你走进FineUI的世界 -此系列内容来源于日常开发积累与沉淀,用于大家学习交流与项目中踩坑 +此系列内容来源于日常开发积累与沉淀,用于大家学习交流与项目中踩坑,掌握一些api文档之外的进阶技巧 ## 100-Questions列表 @@ -13,12 +13,14 @@ FineUI入门100题,带你走进FineUI的世界 - [0、前端工作进阶需要哪些必备技能](./questions/0.前端工作进阶需要哪些必备技能.md) - [1、前端如何正确书写资源路径](./questions/50.前端如何正确书写资源路径.md) - [2、组件的代码设计基本思路](./questions/2.组件的代码设计基本思路.md) +- [3、关于组件引用的奥秘,ref知多少](./questions/3.关于组件引用的奥秘,ref知多少.md) ### 布局篇 - [3、我们为什么要设计el这个属性](./questions/40.我们为什么要设计el这个属性.md) - [4、绝对布局的隐藏知识点](./questions/41.绝对布局的隐藏知识点.md) +- [5、何时会滚动,滚动条位置如何贴边,究竟是怎么回事](./questions/42.何时会滚动,滚动条位置如何贴边,究竟是怎么回事.md) ### Fix数据流篇 @@ -26,6 +28,7 @@ FineUI入门100题,带你走进FineUI的世界 ### 进阶 +- [1、高阶组件的render-props](./questions/4.高阶组件的render-props.md) - [1、如何获取当前时间](./questions/1.如何获取当前时间.md) - [2、如何格式化输出日期](./questions/2.如何格式化输出日期.md) - [3、为什么传递时间信息时候推荐使用时间戳](./questions/3.为什么传递时间信息时候推荐使用时间戳.md) diff --git a/questions/3.关于组件引用的奥秘,ref知多少.md b/questions/3.关于组件引用的奥秘,ref知多少.md new file mode 100644 index 0000000..26c1a8a --- /dev/null +++ b/questions/3.关于组件引用的奥秘,ref知多少.md @@ -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: {}, + }; + } +} +``` \ No newline at end of file diff --git a/questions/4.高阶组件的render props.md b/questions/4.高阶组件的render props.md new file mode 100644 index 0000000..f678f03 --- /dev/null +++ b/questions/4.高阶组件的render props.md @@ -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("点击了"); + }, +}; +``` \ No newline at end of file diff --git a/questions/42.何时会滚动,滚动条位置如何贴边,究竟是怎么回事.md b/questions/42.何时会滚动,滚动条位置如何贴边,究竟是怎么回事.md new file mode 100644 index 0000000..e69de29