computed的实现组件之间的双向绑定
v-model可以在父子组件之间使用,在父组件中使用v-model传入响应式对象。v-model本质上是两个操作,
v-bind:modelValue="formData"@update:model-value
在子组件中用props接收,定义一个计算属性,get的时候获取props中传入的modelValue,set的时候emit发射事件给父组件,理论上可以实现单向数据流式的双向绑定。
我们发现,这样也可以实现子组件传值给父组件的效果,但是并没有输出111111,这就是说,并没有在设置值的时候发射事件给父组件。
computed返回的是ref对象,只有修改这个ref对象的value值的时候才会触发set,因为我们是通过v-model绑定的formData(computed返回的ref对象,自动解包)中的某一个属性,修改属性而不是修改对象本身,set方法是不会调用的,只有修改modelValue对象本身,set才会被调用(原理类似于const一个对象,可以修改对象的属性但是不能修改对象的指向)。
既然没有调用set,也就是说我们没有emit事件,那么为什么可以修改父组件中的值呢?因为我们相当于是get到了props中的modelValue,直接修改了modelValue中的值
这里学到了,只有对computed函数返回的ref对象的值进行修改才会触发set,如果ref对象的值是一个对象,修改这个对象的属性是不会触发computed的set函数的
真正的单向数据流式的双向绑定
出现上面问题的根本原因是,对computed返回的ref对象进行操作时,如果修改的是内部的属性,computed无法监听到响应式对象内部属性的变化。那么我们可以用watch来实现这个效果。
先将传入的modelValue拷贝一份(这里是浅拷贝),避免对原对象直接操作。用watch监听这个对象的改变(deep设置为true),改变的时候触发回调函数,将新的formData发射给父组件。