vue中双向绑定是一个指令v-model,所谓的双绑就是可以绑定一个响应式数据到视图,同时视图中变化能改变该值。
v-model是语法糖,默认情况下相当于:value和@input。使用v-model可以减少大量繁琐的事件处理代码,提高开发效率。
通常在表单项上使用v-model,还可以在自定义组件上使用,表示某个值的输入和输出控制。
比如说我们在input上使用时,我们将xxx的值绑定到表单元素value上<input v-model = "xxx">;如果这个input的类型是checkbox,可以使用true-value和false-value指定特殊的值。对于selest可以通过option元素的value设置元素特殊的值;我们甚至可以结合.lazy,.number,.trim对v-model的行为做进一步限定,这样做出来的东西可以帮我们进行一些业务处理(.number->得到处理后的数字,.trim->处理后去掉空格)。
v-model用在自定义组件上时又会有很大的不同,vue3中它类似于async修饰符,最终展开的结果是modelValue属性的绑定和update:modelValue事件;vue3中我们甚至可以用参数形式指定多个不同的绑定,例如:v-model:foo和v-model:bar,非常强大!
双向绑定的原理其实就是分为两步:模板编译和数据劫持
模板编译:分析模板tempalte,元素节点的属性如果存在
v-html,v-model,{{ }}等属性,需要找到对应的数据,并进行渲染。
数据劫持:当数据data发生改变的时候,重新编译模板。(利用的是Object.defineProperty监听数据变化,watch方法对每个元素进行监听,发布订阅者模式订阅watch对象,发布watch对象中update方法)
模板编译之内存操作元素
模板编译将所有的dom操作都转移到内存中去执行(先创建一个内存对象,然后将所有的dom节点转移到内存对象中),操作完dom元素后再把dom结点转移到根节点上
这个转移其实是为了节约内存空间,因为每颗dom树就相当于一颗真实的树,每个dom节点就相当于树的一个片段,当某个片段发生改变的时候,它下面的所有片段都需要重排,是非常耗性能的。
模板编译之遍历节点
模板编译我们还需要去遍历它的所有节点,监听每个节点的类型(元素节点/文本节点),如果是元素节点的话,一定会存在子节点,这个时候就需要利用递归去做遍历。
模板编译之处理元素节点
如果是元素节点的话,我们需要去进行一个元素的赋值、渲染。- 元素节点需要监听所有的属性名,是否存在双向数据绑定的标志
- 如果存在双向绑定标志,直接获取属性值进行赋值
模板编译之处理文本节点
利用正则获取{{ }}里面的内容,获取的文本节点内容直接赋值给文本节点
数据劫持之监听数据变化
监听数据变化,Object.defineProperty只能监听属性的变化,所以这里需要对对象进行遍历,而监听的每一个属性值可能是对象,所以这里还需要进行递归。
监听有两种方法:get和set
当用户获取数据的时候调用get方法,当用户设置数据的时候调用set方法