Vue 数据双向绑定原理

Vue 是运用的 Object.defineProperty()办法进行的数据劫持,运用 set、get 来检测数据的读写。

MVappearVM 结构首mvvm和mvc的差异要包含两个方面,数据改动更新视图,视图改动更新数据。

视图改动更新数据,假定是像 input 这种标签,可approach以运用 oninput 作业..

数据vue.js是做什么的改动更新视图能够运用 Object.definProperty()的 set 方源码超mvvm和mvc的差异法能够检测数据改动,当数vue.js教程据改动就会触发这application个函数,然后更新视图。

结束进程

咱们知道了怎样结束双向绑定了,首要要对数据进行劫持监听,所以咱们需求设置一个 Observer 函数,用来监听mvvm原理悉数源码特征applicamvvm的了解tion的改动。

假定特征产生了改动,那就要奉告订阅者mvvm办法和mvc的差异 watcher 看是否需求更新数据,假定订阅者有多个,则需求一个 Dep 来搜集这些订阅者,然后在监听器 observ源码怎样做缓存和下载的差异成app软件er 和 watcher 之间进行统一管理。缓存

还需求一个指令解析器缓存和下载的差异 cmvvm形式ompile,对需求监听的节点和特征进行mvvm形式和mvc的差异扫描和解析。

因而,流程大概是这样的:

  1. 结束一个监听器 Obs缓存erver,源码之家app装置下载用来劫持并监听悉数特源码本钱色,假定产生改动,appstore则奉告订阅者。
  2. 结束一个订阅者 Watcher,当接到特征改动的奉告时,实施对应的函数,然后更新视图,运用 Dep 来搜集这些 Watapp装置下载cher。
  3. 结束一个解析器 Compile,用于扫描和解析的节点的相appearanceapprove指令mvvm原理,并根据初始化模板以及初始化相应的订阅器。

Vue2.x 的双向绑定原理及完结

闪现一个 Observevue.js前端开缓存的视频怎样保存到本地发实战r

Observer 是一个数据监听器,中心approach办法是运用 Object.defineProperty()通过递归approachvue.js前端开发实战办法对悉数特征都增加 setter、gmvvm和mvc的差异etter 办法进行监听。

vamvvm原理r library = {
book1: {
name: "",
},
book2: "",
};
observe(library);
library.boappleok1.name = "vmvvm的了解ue声威攻略源码编辑器手机版下载"; // 特征name现已被监听了,现在值为:“vue声威攻略”
library.book2 = "没有此书本"; // 特征book2现已被监听了,现在值为:“没有此书本”
// 为数据增加检测
function defineReacti源码怎样做成app软件ve(mvvm和mvc的差异data, keyvue.js教程, val)源码编辑器手机版下载 {
observe(Vue.jsval); // 递归遍历悉数子特征
let dep = new Dep(); // 新建一个depapplication
Object.de缓存视频怎样转入相册fineProperty(data, key, {
enumerable: true,
configurable:源码 trvue.j源码编辑器编程猫下载s用什么开发工具ue,
get: fun缓存和下载的差异缓存视频吞并app下载ction()vue.js结构 {
if (Dep.targ缓存的视频怎样保存到本地et) {
// 判别是否需求增加订源码编辑器阅者,仅第一次需求增加,之后就appointment不用了,详细看Wa缓存视频吞并app下载app装置下载tcher函数
dep.addSuapplicationb(Dep.targ缓存的视频怎样保存到本地et); // 增加一个订阅者
}
return val;
},
set: function(newVal) {
if (val == newVal) retumvvm源码年代和mvc的差异rn; // 假定值未产生改动就return
val = newV源码编辑器编程猫下载al;
console.log源码(
"特appstore征" + key + "现已被监听了,源码资本现在值为:“" + newVal.toStr源码共享网ing() + "”"
);
dep.novue.js面试题tif源码怎样做成app软件y(); // 假定数据产生改动,就奉告悉数的approavue.js教程ch订阅缓存视频者。缓存文件在哪里
},
});
}
// 监听方针的悉数特征
function observemvvm的了解(data) {
if (!data || typeof data !== "object") {
return; /appreciate/ 假定不是方针就return
}
Object缓存.keys(data).forEach(fun缓存vue.js面试题ction(key) {
defineR缓存文件在哪里eactive(vue.js前端开发实战data, key, data[key]);源码超市
});
}
// Dep 担任搜集订阅者,当特征产生改动时,触发源码之家更新函数。
function Dep() {
this.subs = {};
}
Dep.prototype = {
addSub:application function(sub)源码怎样做成app软件 {
this.subs.push(sub);
},
notify: function(mvvm的了解) {
this.subs.forEach((sub) =>源码编程 suappreciateb.update());
},源码
};

思路剖析中,需求有一个能够包容订阅者音讯订阅器 Dep,mvvm规划办法用于搜集订阅者,在特征产生改动时实施对应的更新函数。

缓存的视频怎样保存到本地代码上看,将订阅器 Dep 增加在 getter 里,是为了让 Watcher 初始化时触发,,apprappreciateove因而,需求判别是否APP需求订阅者。

在 setter缓存视频怎样转入相册 中,appearance假定有数据产生改动,则奉告源码共享网悉数的订阅者,然后订阅者就会更新对应的函数。

到此为止,一个比较完vue.js前端开发实战课后答案好的 Observer 就结束了,接下来开始规划mvvm形式和mvc的差异 Watcher.

结束 Watcher

订阅者 Watcher 需求在初始化的时分将自缓存文件在哪里己增加到订阅器 Deapplicationp 中,咱们现已知道监听器 Observer 是在 get 时实施的 Watcher 操缓存视频怎样转入本地视频作,所以只需求在 Watcher缓存和下载的vue.js面试题差异 初始缓存视频怎样转入相册化的时分触发对应的 get 函数去vuemvvm形式.js官网增加对应的订阅者操作即可。

那给怎样触发 get 呢?由于咱们现已设置了 Object.defineProperty(),所以只需求获取对应的特Vue.js色值就能够触发了。

咱们只需求appreciate在订阅者 Watcher 初始化的时分,在 De源码怎样做成app软件p.mvvm和mvp的差异target 上缓存下订阅者,增加成功之后在将其去掉就能够了。

fu源码超市nction源码怎样做成app软件 Watcher(vm, exp, cb) {
this.cb = cb;
this.vm = vm;源码共享网
this.exp = exp;appstore
this.valu缓存视频兼并app下载e缓存和下载的差异 = this.get(); // 将自己增加到订阅器的mvvm形式操作
}
Watcher.prototype = {
update: function(mvvm形式和mvc的差异) {
this.run();mvvm结构
},
run:app装置下载存视频 funct源码编辑器编程猫下载ion() {
var value = this.vm.data[this.exp];
var oldVal = this.valu缓存视频怎样转入本地视频e;
if (approvevalue !== omvv源码编辑器mappointment规划办法ldValmvvm设计形式) {
this.value = value;
this.cb.call(thi缓存视频怎样转入相册s.vm, value, oldVal);
}
},
get: function() {
Dep.target = this; // 缓存自己,用于判别是否增加watcher。
var value = this.vm.data[this.exp]; // 强制实施监听器里的get函数
De缓存p.target =appearance null; // 开释自己
return value;
},
};

到此为止, 简略的额 Watcher 规划完缓存视频吞并毕,然后mvvm设计形式将 Observer 和 Watcher 相关起来,就能够结束缓存文件在哪里一个简略的的双向绑定了。

由于还没有规划vue.js教程解析器mvvm结构 Compile,所以能够先将模板数据写死。

将代码转化为 ESvue.jsvue.js前端开发实战前端开发实战课后答案6 结构函数的写法,预览试试。

这段代码因mvvm的了解为没有结束编译器而是直接传入了所缓存的视频怎样保存到本地绑定的变量,咱们只在一个节点上设置一个数据(name)进行绑定,然后在页面上进行 new缓存的视频怎样保存到本地 MyVue,就能够结束双向绑定了。

并两秒后进行值得改动,能够看到,页面也产生了改动。

// MyVue
prox源码共享网yKeys(key) {
varVue.js self = this;
Object.defineProperty(thvue.js面试题is, kevue.js官网y, {
enume缓存视频兼并rabapp设备下载le: false,
configurVue.jsable: tru缓存视频在手机哪里找e,
get: fm缓存文件在哪里vvm的了解u缓存和下载的差异nc源码超市tion proxyGmv缓存的视频怎样保存到本地vm规划办法etter() {
return self.data[key];
},
set: function promvvm的了解xySette缓存视频吞并app下载r(newVal) {
self.data[key] = newVal;
}
});
}

上面这段代码的作用是将 this.data 的 key 代理到 this 上,使得我缓存文件在哪里能够便利vue.js用什么开发工具的运用 this.xx 就能够取到 this.data.xx。

结束 C缓存视频兼并ompile

缓存视频吞并app下载管上面结束了双向数据绑定,但是整app装置下载mvvm办法和mvc的差异个进程都没appointment有解析 DOM 节店,而是固定替换的,所以接下来要结束一个解析APP器来做数据的解析appoi源码编辑器手机版下载ntme源码编辑器nt和绑定作业。

解析器 compile 的结束进程:

  1. MVVM析模板指令,并替换模板数据,初始化视图。mvvm的了解
  2. 将模板指定对应的节点绑定对应的更新函数,初始化mvvm和mvc的差异相应的订阅器。

为了解析模板,首要需求解析 DOM 数据,然后对含有 DOM 元素上的对应指令进行处理,因而整个 DOM 操作较为再三,能够新建一个 fragment 片段,将需求的解析的app设备下载 DOM 存入 fragmentappear 片段中在进行处理。

function nodeToFrmvvm的了解agment(eAPPl) {
var fmvvm和m源码编辑器vc的差异ragmen源码t = document.createDocumentFragment();
var child = el.firstCvue.js前端开发实战hild;
while (child) {
//vue.js官网 将Dom元素移入fragment中
fragment.appendChild(child);
child = el.fappleirstChild;
}
return fragment;
}

接下来需求遍历各个节点,对含有相关指令和模板语法appearance的节点进行特别处理,先进行最简略模板语法处理,运用正则解析“{{变量}}”这种办法源码之家的语缓存缓存视频兼并app下载视频变成vue.js前端开发实战课后答案本地视频法。

function compileEapproachlement (el) {
var childNodes = e源码之家l.cvue.js官网hildNodes;
var self = t源码编辑器编程猫下载his;
[].slice.call(childNodes).forEacappreciateh(function(node) {
vapplicationar reg = /{{(.*vu缓存文件在哪里e.js是做vue.js官网什么的apple)}}/; // 匹配{{x源码x}}
v缓存文件在哪里ar text = node.textContent;
if (self.isTextNode(node) &ampappstore;&appleamvue.js官网p; reg.tes源码共享网t(text)) {  // 判别是否是契合这种v缓存视频在手机哪里找ue.js官网办法{{}}vue.js前端开发实战的指令
self.compileText(node, reg.exec(text)[1]);
}mvvm设计形式
if (node.childNod源码共享网es && node.childNodes.length源码怎样做成app软件) {
self缓存视频怎样转入相册.compileElement(node);源码编辑器编程猫下载  // 继vue.js是做什么的续递归遍历子节点
}
}mvvm的了解);
},
function compileTe缓存视频怎样转入相册xt (node, exp) {
var self =mvvm和mvc的差异 this;
var in缓存文件在哪里itText = this.vm[exapplep];
uAPPpd缓存视频吞并ateText(node, initText);  // 将初始化的数据初始化到视图中
new Wavue.js用什么开发工具tcher(this.vm, eappointmentxp, function (value) {  // 生成订阅器并绑定更新函数
self.updateText(node, value);
});
},
function updateText (node, value) {
node.textContvue.js面试题ent = t源码源码共享网本钱ypeof value == 'un缓存视频变成本地视频defined' ? '' : value;
}

获取到最外层的节点后,调用 compileElement 函数,对悉数的子节点进行判别,假源码年代设节点是文本节点切匹配{{}}这种办法的指令,则进行编译处理,初始化对应源码资本的参数。

然后需求对当时参Vue.jsapplication数生成一个对应vue.js缓存视频在手机哪里找前端开发实战的更新函数订阅器,在数据产生改动时更新对应的 DOM。

这样就结束了解析、初始化、编译三个进程了。

接下来改造一个 myVue 就能够运用缓存和下载的差异模板变量进行双向数据绑定了MVVM

增加解析作业

增加完 compile 之后,一个数据双向绑定就根本结束了,接下来就是在源码资本 Compiappreciatele 中增加更多指令的解析编译,比方 v-model、v-on、v-bind 等。

增加一个 v-mmvvm结构odel 和 v-on 解析:app装置下载

function compile(node) {
var nodeAttrs = node.attributes;
var self = this;
Array.prototype.forEach.call(nodeA源码超市ttrs, function(attr) {
var attrNaAPPme = attr.name;
if (isDirective(attr缓存视频变成本地视频Name)源码编辑器手机版下载) {
var exp = attr.value;
var dir = avue.js前端开发实战ttrName.substring(2);
if (isEventDirective(dir)vue.js面试题) {
// 作业指令
self.compileEvent(node, self.vm, exp, dir);
} else {
// v-model 指令
self.compileModelVue.js(node, self.vm, exp, dmvvm原理ir);源码资本
}
nVue.jsode.缓存视频怎样转入相册removeAtvue.源码怎样做成app软件js前端开发实战课后答案t缓存视频怎样转入相册ribute(attrName); // 解析结束,移除特征
}
});
}
// v-指令解析
fumvvm原理nction i源码年代sDirectivevue.js结构(attr) {
return attr缓存视频变成本地视频.ivue.js面试题ndexOf("v-") == 0;vue.js面试题
}
// on: 指令解析
fun缓存视频在手机哪里找ction isEventDirective(dir) {
retuvue.js面试题rn dir.ind源码编辑器编程猫下载exvue.js前端开发实战课后答案Of("on:")app设备下载 === 0;
}

上面的 compile 函数是用于遍历当时 dom 的悉数节点特征,然后判别特征是appreciate否是指令特征,假定是在做对应的处源码编辑器手机版下载理(作业就去监听作业、数据就去监听数据.缓存视频.)

无缺版 mymvvm和mvp的差异Vue

在 MyVue缓存文件在哪里 中增加 mount缓存的视频怎样保存到本地ed 办法,在悉数操作都做完vue.js前端开发实战时施mvvm和mvp的差异行。

clavue.js面试题ss MyVue {
constructor(options) {
var self = this;
this.da源码编程ta = optionsmvvm办法.data;
this.methvue.js用什么开发工具ods = options.methods;
Object.keysapproach(this.dvue.js面试题ata).forEach(function(key) {
svue.js教程emvvm和mvp的差异lf.proxyKeys(key);
});
observe(t源码his.data);
new Compile(o源码编辑器ptions.el, this);
opt缓存视频怎样转入相册ions.mounvue.js教程ted.ca缓存文件在哪里ll(this); // 悉数作业处理好源码编程vue.js前端开发实战课后答案实施moun缓存视频在手机哪里找ted函数
}
proxyKeys(key) {
// 将this缓存视频吞并appMVVM下载.data特征代理到this上
var self = this;mvvm原理
Object.defineapproachPr源码年代operty(mvvm规划方源码年代this, key, {
enumerable: false,
configurable: true,
get: function geappointmenttter() {
return self.data[key];
},
se源码之家t: function settevue.js结构r(newVal) {
self.data[key] = newVal;
},
});
}
}

然后就能够查验运用了。

总结一下流程,回头在哪看一遍这个图,是不是清楚很多了。
Vue2.x 的双向绑定原理及完结

参阅

  • Vue.js 技能揭秘
  • -剖析 Vue.jsappstoremvvmvue.js结构和mvp的差异 内部运行机制
  • 博客园-vuemvvm形式和mvc的差异 的双向绑定原理及结束
  • KKB-源码vue 源码解析
  • vue-study