大家好,我是南宫,今天接着分享一个刚发现的小技巧。最近在用Vue_CLI+ElementUI写一个项目,里面经常出现比较复杂、带有tab的弹窗。比如下面这样:
很明显,这个tab应该使用el-tabs组件,稍微改一改样式就OK了。白色的弹窗是一个自定义组件,里面用一个data来控制显示的tab,初始值可能指定为第一个tab的名字。
那么问题来了,假如我要从父组件打开这个白色弹窗,但是并不希望一进来就看到第一个tab,而是第三个或者第四个tab,怎么办呢?
如图所示,如果选择“发布任务”,则希望一进来就看到第三个tab,如果选择“上传纪要”,则希望一进来就看到第四个tab——换言之,如果一进来的tab是哪个不确定,我们要怎么实现呢?
我当时的想法特别乱——一头是父组件要控制子组件的tab(应该用prop属性传入值),另一头是子组件自己也能控制自己当前显示哪个tab(应该用data属性来控制),怎么同时满足这两头呢?
现在来介绍一下我最后想出来的解决方案:
第一步,想要满足刚才说到的这两头,就要准备这两个属性——在子组件这里,接受父组件传递过来的tab名字(prop,默认值可以设置为第一个),也要有控制自己的当前tab的data属性。
props: {
// 其他代码
// 当前选中哪个tab
defaultActive: {
type: String,
default: 'meetingInfo'
}
},
data: {
return {
// 其他代码
// 当前选中的tab
meetingActive: ''
}
}
<el-tabs v-model="meetingActive" class="detail-tab">
<!-- 第一块,会议信息 -->
<el-tab-pane label="会议信息" name="meetingInfo">...</el-tab-pane>
<!-- 其他的几个tab -->
</el-tabs>
模板上把el-tabs的v-model指定为这个data属性,毕竟要自己控制自己当前的tab。
第二步,想办法把这两个属性连接起来。
可以从参数的角度来思考:假如父组件没有指定tab,控制子组件tab的属性应该为第一个(也可以是其他的)的名字;假如父组件指定了tab,控制子组件tab的属性应该设为父组件传入的那个tab。
所以关键就是——控制子组件的tab的属性的初始值应该跟着父组件指定的tab设置。
第三步,让控制子组件tab的属性的初始值跟着父组件指定的tab。
既然是“跟着”,那就要观察父组件指定的tab了。我们在watch里新增一个对父组件指定的tab的监听:
watch: {
// 其他代码
// 父组件决定它当前的tab
defaultActive: (val) {
this.meetingActive = val
},
}
只要父组件指定的tab发生了改变,马上就把它设为控制子组件的tab的属性的值。
第四步,监听prop属性的注意事项。
写到这里的时候,我感觉一切的思路都顺畅了,肯定可以成功。结果操作起来,我被实际效果打脸了——并没有监听到父组件传来的prop值。
考虑到之前我只监听过data和computed属性,都没有问题,所以我觉得问题可能出在对prop的监听上了。于是我去百度以后,果然得到了改进方案——把这个监听器写成对象的形式,里面加上一个immediate为true的设置:
watch: {
// 父组件决定它当前的tab
defaultActive: {
// 想让监听prop生效
immediate: true,
handler(val) {
this.meetingActive = val
}
},
}
至此,大功告成!如果你也有类似的需求,可以直接使用我的方案呀。如果有更好的方案或者建议,也欢迎给我评论。