一、预备知识
1.1 组件的v-model
前面我们在input中可以使用v-model来完成双向绑定:
- 这个时候往往会非常方便,因为v-model默认帮助我们完成了两件事;
- v-bind:value的数据绑定 和 @input的事件监听;
如果我们现在封装了一个组件,其他地方在使用这个组件时,是否也可以使用v-model来同时完成这两个功能呢?
- 也是可以的,vue也支持在组件上使用v-model;
当我们在组件上使用的时候,等价于如下的操作:
- 我们会发现和input元素不同的只是属性的名称和事件触发的名称而已;
1.2 组件v-model的实现
那么,为了我们的MyInput组件可以正常的工作,这个组件内的 <input>
必须:
- 将其 value attribute 绑定到一个名叫 modelValue 的 prop 上;
- 在其 input 事件被触发时,将新的值通过自定义的 update:modelValue 事件抛出;
1.3 computed实现
我们依然希望在组件内部按照双向绑定的做法去完成,应该如何操作呢?我们可以使用计算属性的setter和getter来完成。
1.4 绑定多个属性
我们现在通过v-model是直接绑定了一个属性,如果我们希望绑定多个属性呢? p也就是我们希望在一个组件上使用多个v-model是否可以实现呢?
- 我们知道,默认情况下的v-model其实是绑定了 modelValue 属性和 @update:modelValue的事件;
- 如果我们希望绑定更多,可以给v-model传入一个参数,那么这个参数的名称就是我们绑定属性的名称;
注意:这里我是绑定了两个属性的
v-model:title相当于做了两件事:
- 绑定了title属性;
- 监听了 @update:title的事件;
二、如果父组件中的v-model绑定的是一个对象,那么使用ref,而不要使用reactive。
2.1 实现方法一(推荐)
2.2 实现方法二(错误)
如果父组件中的v-model绑定的是一个对象,子组件不要采用computed这种做法(违背了Vue单向数据流的原则),而要使用上面子组件中使用ref拷贝一个新对象的做法
- 如果父组件中的v-model绑定的是一个普通的字符串,那么可以采用子组件中使用computed这种做法。
- 因为父组件中的v-model绑定的是一个对象时,对象的属性值发生改变不会触发computed的set函数,
子组件中直接修改了父组件传递过来的modelValue,违背了Vue单向数据流的原则
- 而父组件中的v-model绑定的是一个普通的字符串时,会触发computed的set函数,
子组件中没有直接修改父组件传递过来的modelValue