vue父子组件状态同步的最佳方式续章(v-model篇)

原来的实现方式

自定义的MyInput组件

<template>

  <div class="myInput">

      <!-- 这里只能用 vModel 不可以使用横杠写法 -->

    <input type="text" :value="vModel" @input="inputHandle">

  </div>

</template>

<script>

export default {

  name: "MyInput",

  props: {

      // 这里也可以写成 'v-model': String 但是建议根据风格来,如果左边都没有引号就直接驼峰

    vModel: String

  },

  methods: {

    inputHandle (event) {

        // 注意:这里使用 update:v-model 或 update:vModel 都可以

      this.$emit("update:v-model", event.target.value)

    }

  }

}

</script>

使用方式

// 方式一

<my-input :v-model="text" @update:v-model="text = $event"></my-input>

// 方式二

<my-input :v-model.sync="text"></my-input>

可以看到,原来的方式也能实现,但是就使用来说v-model被当成属性,一定要在前面加上:才可以用动态属性,结果就变成了:v-model,然后我们为了简化写法去掉事件绑定,我们最终的效果就是 :v-model.sync这种写法总会让人觉得怪怪的,接下来我们就来解决这个问题

vue-api的方式实现

自定义的MyInput组件

<template>

  <div class="myInput">

    <input type="text" :value="value" @input="inputHandle">

  </div>

</template>

<script>

export default {

  name: "MyInput",

  props: {

    value: String

  },

  methods: {

    inputHandle (event) {

      this.$emit("input", event.target.value)

    }

  }

}

</script>

使用方式

<my-input v-model="text"></my-input>

看到这里可能一部分同学会一脸懵逼,这就同步了?emm,其实还真同步了,那 value 从哪儿来的,input 事件也没绑定啊,的确这些都被我们省略掉了,其实这是 vue 的 api 带给我们的便利,在我们试图向自定义组件传入 v-model 这个特殊的属性的时候,vue 会帮我们做两件事,一件是将 v-model 中的值作为 value 的值向下传递,这是我们在内部要写 props value 的原因,另一件是在当前自定义组件上监听 input 事件,并在触发改事件的时候,将第一个参数赋值给 v-model 中的变量。你可以看到在我们肉眼不可见的地方 vue 为我们做了很多实际,但是大家要明白他为什么给你做这么多,仔细想想不难看出,这些逻辑是业务场景中重复次数很多的逻辑, vue 不给你做,你自己也要做,还会闲麻烦!当然这还没结束呢!下面更精彩!

为属性 value 和事件 input 命名

有些时候我们可能希望 value 就作为一个普通的属性往下传,而我们的业务场景里面 input 作为事件也不够形象,反正就是 value 和 input 不符合你的业务中的语义,这个时候我想改名,咋办?接下来看下面的代码:

<template>

  <div class="myInput">

    <input type="text" :value="text" @input="inputHandle">

  </div>

</template>

<script>

export default {

  name: "MyInput",

  model: {

    prop: "text", // 该属性名

    event: "update:v-model" // 改事件名

  }

  props: {

    text: String // 即便改名了,这里也必不可少

  },

  methods: {

    inputHandle (event) {

      this.$emit("update:v-model", event.target.value)

    }

  }

}

</script>

深圳网站优化www.zg886.cn

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。