网站建设功能需求表,邢台市招聘信息最新招聘信息,让别人做网站要注意什么6,接做网站单子文章目录 VUE2双向绑定的原理1. 什么是双向绑定2. 双向绑定的原理2.1 ViewModel的重要作用2.2 双向绑定的流程 3. 双向绑定的实现3.1 data响应化处理3.2 Compile编译3.3 依赖收集 VUE2双向绑定的原理
1. 什么是双向绑定
讲双向绑定先讲单项绑定#xff0c;啥叫单项绑定… 文章目录 VUE2双向绑定的原理1. 什么是双向绑定2. 双向绑定的原理2.1 ViewModel的重要作用2.2 双向绑定的流程 3. 双向绑定的实现3.1 data响应化处理3.2 Compile编译3.3 依赖收集 VUE2双向绑定的原理
1. 什么是双向绑定
讲双向绑定先讲单项绑定啥叫单项绑定就是一句话就是通过Model去改变View再直白点就是通过js代码把数据改变后html视图也跟着变化那双项绑定就很好理解了在单项绑定的基础上如果view改变了Model也能同步变化一句话概括就是Model变化View跟着跟新View跟新Model跟着变化这就是双向绑定
2. 双向绑定的原理
其实我们可以很容易想到一点就是如果A变化了想要B跟着变化最简单的方式就是A变化的时候通知一下B就行这就是基本思路在VUE2 中双向绑定由三个重要部分构成
数据层Model应用的数据及业务逻辑视图层View应用的展示效果理解为UI组件业务逻辑层ViewModel框架封装的核心他主要负责把数据层和视图层关联起来这就是MVVM模型
2.1 ViewModel的重要作用
ViewModel主要干两件事
数据变化后更新视图视图变化后更新数据
那么问题来了怎么通知呢我们怎么知道数据变化后通知哪些视图呢这要依赖ViewModel的两个重要部件
监听器Observer,对所有数据的属性进行监听解析器Compiler,对元素节点的指令进行扫描跟解析根据指令模板替换数据以及绑定相应的更新函数
2.2 双向绑定的流程
双向绑定的流程
我们在new Vue时执行初始化对data执行相应化处理这个过程发生在Observer中同时对模板执行编译找到其中动态绑定的数据从data中获取并初始化视图这个过程发生在Compiler中同时定义一个更新函数和Watcher将来对应数据变化时Watcher会调用更新函数由于data中的数据的某个key可能出现在视图的多处所以每个key都需要一个管家Dep来管理多个Watcher将来数据一旦发生变化会首先找到对应的Dep通过Dep李曼的所有Watcher执行更新函数
3. 双向绑定的实现
3.1 data响应化处理
我们来创建一个构造函数执行初始化对data数据执行响应化处理
class Vue{constrcutor(options){this.$optionsoptions;this.$dataoptions.data;//对data选项做响应式处理Observe(this.$data)//代理data到vm上proxy(this)// 执行编译new Compile(options.el,this)}
}
function Observe(obj){if(typeof obj!object || objnull){return;}new Observer(obj)
}
class Observer{constructor(value){this.valuevalue;this.walk(value)}walk(obj){Object.keys(obj).forEach((key){defineReactive(obj,key,obj[key])//内部是Object.defineProperty实现后面会讲})}
}
3.2 Compile编译
对元素节点的指令机型扫描跟解析根据指令模板替换数据以及绑定相应的更新函数
class Compile{constructor(el,vm){this.$vmvm;this.$eldocument.querySelector(el);//获取DOMif(this.$el)this.compile(this.#el)}compile(el){const childNodesel.ChildNodes;Array.from(childNodes).forEach((node){//遍历子元素if(this.isElement(node)){//判断是否为节点/*编译元素*/}else if(this.inInterpolation(node)){//是否为差值文本/*编译差值文本*/}if(node.childNodes node.childNodes.length0){this.compile(node)}})}isElement(node){return node.nodeType1}isInterpolation(node){return node.nodeType3 /\{\{(.*)\}\}/.test(node.textContent)}
}3.3 依赖收集 视图中会用到data中的某个key这被称为依赖一个key可能出现在视图中的多个位置每次都需要收集出来用一个Watcher来维护他们这个过程被称为依赖收集很多歌Watcher需要一个Dep来管理需要更新时由Dep统一通知 基本思路
defineReactive为每一个key创建一个Dep比如data1创建Dep1初始化视图时读取某个key例如data1就创建一个watcher1由于读取key时触发getter方法边疆watcher1天假到data1的Dep1中份当data1更新时触发setter通过Dep1通知所有的watcher更新
class Wacther{constructor(vm,key,updater){this.$vmvm;this.$keykey;this.updaterFnupdater;//创建实例时把当前实例指定到Dep.target静态属性上Dep.targetthis;vm[key]//读一下key触发getDep.targetnullupdate(){this.updaterFn.call(this.$vm,this.$vm[this.$key])}}
}
class Dep{constructor(){this.deps[];//依赖管理 }addDep(dep){this.deps.push(dep)}notify(){this.deps.forEach((dep){dep.update()})}
}
// 创建Watcher时触发getter
function defineReactive(obj,key,val){this.observe(val)const depnew Dep()Object.defineProperty(obj,key,{get (){Dep.target dep.addDep(Dep.target)//Dep.target就是Watcher实例return val},set(newVal){if(newValval)returndep.notify()//通知dep执行更新方法 }})
}