谈及Vue中的数据双向绑定,咱们天然而然的想到是经过v-model指令实现的。但具体是怎么实现的呢?下面就介绍一下。javascript
v-model语法糖是vue多个基础语法(属性绑定 和事件绑定)的简写。html
原理:给表单元素input绑定经过"v-bind:"绑定value属性的数据msg,再给表单元素input添加监听value值改变的事件@input,给msg从新赋值。vue
代码:java
<!-- <input type="text" v-model="msg"> --> <input :value="msg" type="text" @input="msg=$event.target.value">
vue中数据双向绑定经过v-model实现,双向绑定指的是视图和内存中的数据进行双向绑定。(经过Object.defineProperty和给元素注册事件)node
表单元素改变数据的原理:
算法
经过给表单元素注册input事件,将表单元素中的value值赋给vue.msg浏览器
<!-- 1. 把数据渲染到表单元素中 --> <!-- 2. 当你修改数据的时候,表单元素的值发生改变,视图须要更新 --> <!-- 3. 当你使用表单元素的时候,你在修改元素的值,对应的数据也要发生改变 --> <h5></h5> <input type="text"> <script> // const vm = new Vue({data:{msg:'hi vue'}}) vm.msg = '数据' // 使用用定义能够监听(观察)的属性的。 const vm = {} const data = { msg: 'hi vue' } // 获取dom const h5 = document.querySelector('h5') const input = document.querySelector('input') // 1. 默认渲染 h5.innerHTML = data.msg input.value = data.msg // 2.1 监听 data中的msg的值改变 观察 data中的msg的值改变 最终监听的是vm的msg属性变化 // 2.2 若是 数据改变 修改视图 // 三个参数 给谁定义一个属性 属性的名称 对象配置项(get 获取属性值 set 设置属性值) Object.defineProperty(vm, 'msg', { get() { // 当获取msg属性值时触发 // console.log('get') return data['msg'] }, set(newValue) { // 当设置msg属性值时触发 // console.log('set') // console.log(newValue) // 数据改变 data['msg'] = newValue // 修改视图 h5.innerHTML = newValue input.value = newValue } }) // 3. 监听 表单元素 的值改变事件 修改数据便可(上面已经实现数据驱动视图) input.oninput = function(){ // console.log(this.value) vm.msg = this.value } </script>
整体描述:dom
Vue内部会把data中的数据经过defineProperty方法转化为set和get的监控方式函数
当data中的数据发生变化时,会触发对应的set或者get性能
修改属性值的时候,触发set方法
访问属性值的时候,触发get方法
监控数据变化的目的仍是为了更新页面(仅仅更新数据变化对应的DOM节点:尽量少的更新DOM)
可是完成上述要求须要底层虚拟DOM的支持
浏览器更新DOM比较耗时,为了节省时间,须要尽量少的更新DOM。虚拟DOM是对真实DOM的一种描述;其组成部分虚拟节点也描述了真实的DOM节点,本质上就是普通对象
// VNODE 虚拟节点:描述了真实的DOM节点,本质上就是普通对象 { tagName: 'div' attrs: { class: "active", id: "info"} content: "hello" }
虚拟DOM也会造成一个树状结构,描述了真实的DOM树(造成虚拟DOM树和真实DOM树的对应关系)
若是数据发生变化,那么就会触发虚拟DOM数的对比(diff算法,过程发生在内存中)
对比的结果是:有变化的虚拟节点的集合
上述虚拟节点须要转化为真实的DOM节点(下面是虚拟下面是虚拟节点转换为真实节点的过程)
var div = document.createElement(vnode.tagName) div.setAttibute(key, value) div.innerHTML = vnode.content
双向数据绑定运用虚拟DOM的进一步解释说明:
在使用defineProperty进行到set()时,会采用虚拟DOM来跟新视图;虚拟DOM有新、旧两份数据存储在内存中,每次监测到数据改变时,计算机会经过diff算法对比两份数据的区别,获得有变化的虚拟节点的集合,并将它们转换为真实的DOM节点更新到页面中。
采用上面方式的缘由就是浏览器解析完整DOM树的时间、性能消耗,要远比内存对比数据再进行局部渲染的消耗大得多。内存处理数据的速度要比浏览器快的多。