利用vue组件自定义v-model实现一个Tab组件方法示例(2)
传进来的 options 缺少些参数,我们每个选项需要 active 来标记是否是选中状态,需要 disabled 来标记是否是禁选状态,所以拷贝一个 currOptions 来补全不足参数。
另外直接改变 value 这个 props 是没有效果滴,所以拷贝一个 value 的副本,叫 currValue。
<!-- Tab.vue --> <script> export default { props: { value: { type: String }, options: { type: Array, default: [] } }, data() { return { // 拷贝一个 value currValue: this.value, currOptions: [] } }, mounted() { this.initOptions(); }, methods: { initOptions() { // 拷贝一个 options this.currOptions = this.options.map(item => { return { ...item, active: item.value === this.currValue, disabled: !!item.disabled } }); } } } </script>
🆗接下来再在选项上绑定击事件就 OK 了。
既然知道父组件会接受 input 事件,那我们就只需要 this.$emit('input', this.currValue); 就好了。
<!-- Tab.vue --> <template> <div class="tab"> <div class="item" v-for="(item, i) in options" :key="i" @click="onTabSelect(item)"> <!-- ↑ 这里绑定了一个事件! --> {{item.text}} </div> </div> </template> <script> export default { props: { value: { type: String }, options: { type: Array, default: [] } }, data() { return { currValue: this.value, currOptions: [] } }, mounted() { this.initOptions(); }, methods: { initOptions() { this.currOptions = this.options.map(item => { return { ...item, active: item.value === this.currValue, disabled: !!item.disabled } }); }, // 添加选中事件 onTabSelect(item) { if (item.disabled) return; this.currOptions.forEach(obj => obj.active = false); item.active = true; this.currValue = item.value; // 发布 input 事件,↓ 父组件如果有 v-model 就会监听到的。 this.$emit('input', this.currValue); } } } </script>
剩下的补上点样式还有 watch 下 value 和 options 的变化就可以了,最后贴上完整代码。
完整代码
<!-- example.vue --> <template> <div> <Tab v-model="tab" :options="options"></Tab> <p class="info">{{tab}}</p> </div> </template> <script> import Tab from '~/Tab'; export default { components: { Tab }, data() { return { tab: 'bj', options: [{ value: 'bj', text: '北京' }, { value: 'sh', text: '上海', disabled: true }, { value: 'gz', text: '广州' }, { value: 'sz', text: '深圳' }] } } } </script> <style lang="less" scoped> .info { margin-left: 50px; font-size: 30px; } </style>
内容版权声明:除非注明,否则皆为本站原创文章。