美文网首页让前端飞
vue组件兼容v-model

vue组件兼容v-model

作者: 我是你班主任 | 来源:发表于2019-01-09 18:01 被阅读0次

    组件系统作为Vue最重要的部分之一,多人协作开发的时候,写好一个可复用的组件灰常重要,别的同事用到你写的组件的时候会觉得:“诶,这个小伙汁有点东西!”

    • 如果不用v-model,在原生input标签上怎么实现双向绑定呢?
    <template>
      <input :value="text" @input="handler" />
    </template>
    <script>
      export default {
        name: 'customInput',
        data () {
          return {
            text: 'message'
          }
        },
        methods: {
          handler () {
            this.text = this.$event.target.value
          }
        }
      }
    </script>
    

    v-model就是上面操作的语法糖

    • 下面我们来实现一个简单的星级组件并兼容v-model
    <template>
      <div class="component-star" @click.stop="">
        <ul class="star-list">
          <li v-for="(item, index) in list" :key="index" @click="change(index)">{{item}}</li>
        </ul>
        <span class="label">{{label}}</span>
      </div>
    </template>
    
    <script>
      export default {
        name: 'myStar',
        props: {
          value: { // 必须是value属性,名字不能变
            type: [Number, String],
            required: true
          }
        },
        data () {
          return {
          }
        },
        computed: {
          list () {
            return '★★★★★☆☆☆☆☆'.slice(5 - this.value, 10 - this.value).split('')
          },
          label () {
            const arr = ['1星', '2星', '3星', '4星', '5星']
            return arr[this.value - 1]
          }
        },
        watch: {
        },
        methods: {
          // 当星级变化
          change (val) {
            let num = val + 1
            this.$emit('input', num) // 必须是input事件
          }
        }
      }
    </script>
    
    <style lang="less">
      .component-star {
        .star-list {
          display: inline-flex;
          font-size: 20px;
          li {
            cursor: pointer;
            margin-right: 5px;
            color: #f7ba2a;
            transform: scale(1);
            transition: transform .1s linear;
            &:hover {
              transform: scale(1.3);
            }
          }
        }
      }
    </style>
    

    有两个关键的地方:
    1、组件的props中必须要定义value属性
    2、当值变化后,一定要用input事件回传修改后的值

    写好注册就可以在任意组件中使用了

    <template>
      <div class="parent">
        <my-star v-model="star"></my-star>
      </div>
    </template>
    <script>
      export default {
        name: 'parent',
        data () {
          return {
            star: 3
          }
        },
        watch: {
          star (val) {
            console.log(val)
          }
        }
      }
    </script>
    

    那么问题来了:如果我编写的组件内部还有一个使用v-model的组件怎么办呢?

    比如刚才的组件我想在element提供的el-rate组件基础上做一层封装,只需要把"v-model"替换为":value",这样功能即可正常使用。(当然,如果你是按需加载element组件的话,不要忘了先注册组件)

    <template>
      <div class="component-star" @click.stop="">
        <!--只需要把v-model替换为:value-->
        <el-rate :value="value" @change="change" ref="rate"></el-rate>
      </div>
    </template>
    

    如果报了这个错:[Vue warn]: Invalid prop: type check failed for prop "value". Expected Number, got String.说明你传进来的value是个String类型的值,el-rate的value参数只接受Number类型的值,把组件v-model绑定的变量改成数字类型就好了。


    是不贼简单?组件兼容了v-model你就是这条该上最靓的那个仔!

    相关文章

      网友评论

        本文标题:vue组件兼容v-model

        本文链接:https://www.haomeiwen.com/subject/ijwzkqtx.html