iview级联选择组件源码阅读笔记
组件划分
cascader组件共划分成了三个组件:
- cascader.vue
- caspanel.vue
- casitem.vue
其中,cascader是最外层的组件,包括一个slot和caspanel。slot内部默认是一个input框。
caspanel则是弹出的面板,里面包括若干个casitem选项,和一个子caspanel面板(如果有)。
casitem则是简单的选项组件,存放选项。
DOM结构
大致的DOM结构如下:
1 | <Cascader> |
逻辑思路
在页面渲染时,通过computed中的querySelections
方法对data进行遍历修改,添加__label
__value
属性
在点击slot中的内容时,调用toggleOpen
方法,修改visible
属性控制Caspanel
的显隐:
1 | //以下三个函数用于控制this.visible,由此控制panel的显隐 |
然后在watch中监听visible
属性的变化,当input中有值时,更新面板的内容,使面板展示选中的项:
1 | visible (val) { |
1 | updateSelected (init = false) { |
在updateSelected
中,会广播on-find-selected
事件,在处理该事件的函数中,还会触发on-clear
事件,将Caspanel
的子面板都清空,然后再渲染新的子面板(展示选中的项),并设置选中的value。
当用户点击最后要选择的选项时,Caspanel
组件会调用一个方法先改变父组件Cascader
的this.tmpSelected
,然后触发on-result-change
事件,驱使父组件更新this.selected
和this.currentValue
,从而更新DOM。
疑惑:
在Caspanel
组件中,使用了this.$parent
来调用父组件Cascader
的方法,甚至用到了this.$parent.$parent
,在其他组件中有看到直接通过this.$parent
修改父组件中的属性值,不知这种方式与通过事件来通知父组件从而改变父组件中的属性,哪种更合适一些。
1 | emitUpdate (result) { |