利用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>
      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/1120.html