推荐设备MORE

免费制作网页

免费制作网页

疑难问题

漯河微信小程序开发_浅析vue 函数配置项watch及函

日期:2021-01-08
我要分享
浅析vue 函数配置项watch及函数 $watch 源码分享       这篇文章主要介绍了vue 函数配置项watch及函数 $watch 源码分享 ,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下

Vue双向榜单的原理

大家都知道Vue采用的是MVVM的设计模式,采用数据驱动实现双向绑定,不明白双向绑定原理的需要先补充双向绑定的知识,在watch的处理中将运用到Vue的双向榜单原理,所以再次回顾一下:

Vue的数据通过Object.defineProperty设置对象的get和set实现对象属性的获取,vue的data下的数据对应唯一 一个dep对象,dep对象会存储改属性对应的watcher,在获取数据(get)的时候为相关属性添加具有对应处理函数的watcher,在设置属性的时候,触发def对象下watcher执行相关的逻辑

// 为data的的所有属性添加getter 和 setter
function defineReactive( obj,key,val,customSetter,shallow
 var dep = new Dep();
 /*....省略部分....*/
 var childOb = !shallow observe(val); //为对象添加备份依赖dep
 Object.defineProperty(obj, key, {
 enumerable: true,
 configurable: true,
 get: function reactiveGetter() {
 var value = getter getter.call(obj) : val;
 if (Dep.target) {
 dep.depend(); // 
 if (childOb) {
 childOb.dep.depend(); //依赖dep 添加watcher 用于set ,array改变等使用
 if (Array.isArray(value)) {
 dependArray(value);
 return value
 set: function reactiveSetter(newVal) {
 var value = getter getter.call(obj) : val;
 /* eslint-disable pare */
 if (newVal === value || (newVal !== newVal value !== value)) {
 return
 /* eslint-enable pare */
 if ("development" !== 'production' customSetter) {
 customSetter();
 if (setter) {
 setter.call(obj, newVal);
 } else {
 val = newVal;
 childOb = !shallow observe(newVal);
 dep.notify();//有改变触发watcher进行更新
} 

在vue进行实例化的时候,将调用 initWatch(vm, opts.watch);进行初始化watch的初始化,该函数最终将调用 vm.$watch(expOrFn, handler, options) 进行watch的配置,下面我们将讲解 vm.$watch方法

Vue.prototype.$watch = function (
 expOrFn,
 options
 var vm = this;
 if (isPlainObject(cb)) {
 return createWatcher(vm, expOrFn, cb, options)
 options = options || {};
 options.user = true;
 //为需要观察的 expOrFn 添加watcher ,expOrFn的值有改变时执行cb,
 //在watcher的实例化的过程中会对expOrFn进行解析,并为expOrFn涉及到的data数据下的def添加该watcher
 var watcher = new Watcher(vm, expOrFn, cb, options);
 //immediate==true 立即执行watch handler
 if (options.immediate) { 
 cb.call(vm, watcher.value);
 //取消观察函数
 return function unwatchFn() {
 watcher.teardown();
 };

来看看实例化watcher的过程中(只分享是观察函数中的实例的watcher)

var Watcher = function Watcher(
 expOrFn,
 options,
 isRenderWatcher
 this.vm = vm;
 if (isRenderWatcher) {
 vm._watcher = this;
 vm._watchers.push(this);
 // options
 if (options) {
 this.deep = !!options.deep; //是否观察对象内部值的变化
 this.user = !!options.user;
 this.lazy = !!options.lazy;
 this.sync = !!options.sync;
 } else {
 this.deep = this.user = this.lazy = this.sync = false;
 this.cb = cb; // 观察属性改变时执行的函数
 this.id = ++uid$1; // uid for batching
 this.active = true;
 this.dirty = this.lazy; // for lazy watchers
 this.de凡科抠图 = [];
 this.newDe凡科抠图 = [];
 this.depIds = new _Set();
 this.newDepIds = new _Set();
 this.expression = expOrFn.toString();
 // parse expression for getter
 if (typeof expOrFn === 'function') {
 this.getter = expOrFn;
 } else {
 // 将需要观察的数据:string | Function | Object | Array等进行解析 如:a.b.c, 并返回访问该表达式的函数 
 this.getter = parsePath(expOrFn); 
 if (!this.getter) {
 this.getter = function () { };
 "development" !== 'production' warn(
 "Failed watching path: \"" + expOrFn + "\" " +
 'Watcher only accepts simple dot-delimited paths. ' +
 'For full control, use a function instead.',
 // this.get()将访问需要观察的数据 
 this.value = this.lazy
 undefined
 : this.get(); 
 * Evaluate the getter, and re-collect dependencies.
 Watcher.prototype.get = function get() {
 //this为$watch方法中实例化的watcher
 pushTarget(this);讲this赋给Dep.target并缓存之前的watcher
 var value;
 var vm = this.vm;
 try {
 //访问需要观察的数据,在获取数据的getter中执行dep.depend();将$watch方法中实例化的watcher添加到对应数据下的dep中
 value = this.getter.call(vm, vm); 
 } catch (e) {
 if (this.user) {
 handleError(e, vm, ("getter for watcher \"" + (this.expression) + "\""));
 } else {
 throw e
 } finally {
 // "touch" every property so they are all tracked as
 // dependencies for deep watching
 if (this.deep) {
 traverse(value);
 popTarget(); //将之前的watcher赋给Dep.target
 this.cleanupDe凡科抠图();
 return value
 }; br br br br 
 Watcher.prototype.run = function run() {
/*....省略部分....*/ 
 var value = this.get(); //的值
 var oldValue = this.value; //保存老的值
 this.value = value;
 this.cb.call(this.vm, value, oldValue); //执行watch的回调
/*....省略部分....*/ 
 };

以上代码在watcher实例化的时候执行  this.getter = parsePath(expOrFn); 返回一个访问该属性的函数,参数为被访问的对象  如vm.$watch("info",function(new, old){console.log("ess")});, this.getter =function(obj){};,在执行watcher的get方法中,将执行value = this.getter.call(vm, vm);,属性对应的def对象中,如果需要深度监听,将执行traverse(value),只对象)的属性还有是对象的属性,下所有的属性的def对象都会添加该watcher实例。

  ="change"的set方法,执行dep.notify();出发info所依赖的watcher执行watcher的run方法,即实现监听

总结

以上所述是小编给大家介绍的vue 函数配置项watch及函数 $watch 源码分享,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对凡科网站的支持!