💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
MVVM 模式在于数据与视图的保持同步,数据改变时会自动更新视图,视图发生变化时会更新数据。 那么如何检测到**数据的变化**然后通知去更新视图?如何检测到**视图的变化**然后去更新数据? - 1,通过建立虚拟dom树document.createDocumentFragment(),方法创建虚拟dom树。 - 2,一旦被监测的数据改变,会通过Object.defineProperty定义的数据拦截,截取到数据的变化。 - 3,截取到的数据变化,从而通过订阅——发布者模式,触发Watcher(观察者),从而改变虚拟dom的中的具体数据。 - 4,最后,通过更新虚拟dom的元素值,从而改变最后渲染dom树的值,完成双向绑定 ![](https://img.kancloud.cn/9d/94/9d94be5e4435017e6af85d0e322d4fd3_764x393.png) ## Vue是如何实现数据双向绑定的? > Vue数据双向绑定是指:数据变化更新视图,视图变化更新数据,例如输入框输入内容变化时,data中的数据同步变化;data中的数据变化时,文本节点的内容同步变化 Vue主要通过以下4个步骤实现数据双向绑定 * **实现一个监听器「Observer」**: 对数据对象进行遍历,包括子属性对象的属性,利用`Object.defineProperty()`在属性上都加上`getter`和`setter`,这样后,给对象的某个值赋值,就会触发`setter`,那么就能监听到数据变化 * **实现一个解析器「Compile」:** 解析`Vue`模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新 * **实现一个订阅者「Watcher」:** `Watcher`订阅者是`Observer`和`Compile`之间通信的桥梁,主要任务是订阅`Observer`中的属性值变化的消息,当收到属性值变化的消息时,触发解析器`Compile`中对应的更新函数 * **实现一个订阅器「Dep」:** 订阅器采用发布-订阅设计模式,用来收集订阅者`Watcher`,对监听器`Observer`和订阅者`Watcher`进行统一管理 -------------------------------------------------------------------------------------- <div id="div7"><h3> <font color=red > 手写 双向绑定 </font><h3></div> ```javascript let obj = {} let input = document.getElementById('input') let span = document.getElementById('span') Object.defineProperty(obj, 'text', { // 数据劫持 configurable: true, enumerable: true, get() { console.log('获取数据了') }, set(newVal) { console.log('数据更新了') input.value = newVal span.innerHTML = newVal } }) input.addEventListener('keyup', function(e) { // 输入监听 obj.text = e.target.value }) ``` ## vue 从初始化页面--修改数据--刷新页面 UI 的过程 当 Vue 进入初始化阶段时,一方面 Vue 会遍历 data 中的属性,并用 Object.defineProperty 将它转化成 getter/setter 的形式,实现数据劫持(暂不谈 Vue3.0 的 Proxy); 另一方面,Vue 的指令编译器 Compiler 对元素节点的各个指令进行解析,初始化视图,并订阅 Watcher 来更新试图,此时 Watcher 会将自己添加到消息订阅器 Dep 中,此时初始化完毕。 当数据发生变化时,触发 Observer 中 setter 方法,立即调用 Dep.notify(), Dep 这个数组开始遍历所有的订阅者,并调用其 update 方法,Vue 内部再通过 diff 算法,patch 相应的更新完成对订阅者视图的改变。 ## Vue的响应式原理 - 任何⼀个 Vue Component 都有⼀个与之对应的 Watcher 实例。 - Vue 的 data 上的属性会被添加 getter 和 setter 属性。 - 当 Vue Component render 函数被执⾏的时候, data 上会被 触碰(touch), 即被读, getter ⽅法会被调⽤, 此时 Vue 会去记录此 component 所依赖的所有 data。(这⼀过程被称为依赖收集) - data 被改动时(主要是⽤户操作), 即被写, setter ⽅法会被调⽤, 此时 Vue 会去通知所有依赖于此 data 的组件去 调⽤他们的 render 函数进⾏更新。