如何使用vue中的v-model指令来提升编码效率
前言
在
vue
中,v-model
指令用于实现表单输入元素和应用程序状态之间的双向数据绑定,比如像<input>
、<textarea>
、<select>
,使用v-model
可以很方便地将表单的值绑定到vue实例的数据上,实现双向数据绑定,本文主要是通过对比在v3.4版本前后的使用对比,进而在后续的项目中大力采用这个v-model
来简化纯父子组件之间的通讯机制!
vue3.4之前关于在组件中v-model的使用
自定义组件需要手动接收
value
属性,并通过$emit
触发input
事件,来更新父组件的值
1 | <template> |
vue3.4之后关于在组件中 v-model的使用
从
vue3.4
开始,推荐使用的实现方式是使用defineModel()
宏:
1 | <!-- Child.vue --> |
然后,在父组件中可以用v-model
绑定一个值:
1 | <Child v-model="count"/> |
😕 这个过程发生了什么了呢?为什么直接使用v-model + defineModel()
就可以替换掉之前那么复杂的实现呢?
defineModel()的过程
defineModel()
的返回值应该是一个ref,它可以像其他的ref一样被访问以及修改,不过它能够起到在父组件和当前变量之间的双向绑定的作用, 😖 但是,又为什么使用defineModel()
所创建出来的ref就可以实现双向的数据绑定了呢?
按照官方文档的解释:defineModel
是一个便利宏,它主要做了两件事:
- 创建一个名为
modelValue
的属性,然后本地的ref(即在data中创建另外一个ref,我这里称之为dataModelRef
)与这个modelValue
同步,这里的同步采用watch
的方式来实现;- 声明一个名为
update:modelValue
的回调方法,当上述的dataModelRef
的值发生变化的时候,将自动触发这个方法,这里的自动触发,也是通过采用watch
的方式来实现的自动触发!
这里关于数据的流动方向依然还是保持一条路径,也就是父组件定义变量,然后传递给子组件,子组件做展示,当子组件需要更新时,父组件接收事件更新调用,更新父组件变量,然后再传递给子组件继续做展示!!
🤩 可以看一下关于其中生成的父子组件的成员变量
v-model例子
v-model自定义modal 通过上面的例子我们可以看出,在后续的自定义组件中,可直接使用v-model + defineModel() + v-model
的方式,来创建双向绑定的自定义组件
父组件定义子组件的属性,子组件仅做可视化展示(vue2+)
在
vue
coding过程中,经常会使用到父子组件的通信,一般是父组件通过传递属性给到子组件,然后子组件接收到属性,并另外定义一data属性,作为子组件中的绑定,并在data属性更新的时候,通过$emit()
的方式触发父组件去更新父组件中所定义的属性,完成父子组件间的通讯闭环
如果将这个属性直接传递给子组件,然后子组件直接通过v-model
的方式来实现双向绑定的话,则会提示重复渲染的问题,如下图所示:
:-1: 因此,不能直接使用子组件来做双向绑定更新父组件的属性, 👉 这里是由于父组件传递的是一基本数据类型的属性,基本数据类型的传递一般是值传递,当子组件通过v-model
绑定到传递过来的基本数据类型属性时,所触发的操作将会导致子组件不断的重复渲染,因此才会有上述 ☝ 的问题!
😕 但是,如果子组件所接收参数过多的话,通过来回这样子通讯的话,估计维护惨了,这个时候,可以选择采用将相关的属性合并到一个对象中,将对象作为一属性进行传递,然后子组件通过v-model
的方式直接引用,这样子当子组件通过v-model
对传递过来的属性进行更新时,将会通过对象引用的方式来进行的更新操作,因此能够正常的进行双向绑定更新操作! 👉 也就是说,我们可以将所有的响应式变量定义到父组件中,然后子组件所需要的变量由父组件通过对象的方式来传递,子组件通过v-model
的方式来对属性进行双向绑定,这可以大大减少父子组件通讯的代码量,而且交由子组件的双向绑定,可减少重复的props/emit
操作!!!
总结
其实
vue3.4+
的版本,提供的defineModel
宏,与自己单独一个个去编写对应的代码来控制无异,两者在使用过程上是没什么区别的,但是使用了defineModel
可以大大减少这个重复的代码量,再也不用去定义props,然后接收props,同时再定义emit,然后触发对应的emit动作,并传递参数, 👉 而是通过”类model”的props的定义(通过defineModel来创建),然后直接更新创建出来的model属性即可完成双向绑定的目的!! :+1: 后续在这种父子组件之间的通讯的时候,完完全全可以使用v-model:属性
的方式来实现父子组件之间的通讯机制!!