Vue MVVM模型原理

最近反思了下自己,觉得自己很急躁,学技术总是觉得能用就行了,其实这样很不好,总是这样,就永远只能当用轮子的人。好了,废话不多说,转入正题:

要理解MVVM的原理,首先要理解它是什么,怎么运作起来的:

以下这样图来自这位大佬的文章《Vue.js入门(一)--MVVM框架理解》

由图可见,MVVM模型需要靠Observer(监视者)、Compile(解析器)、Dep(Dependency,收集依赖)、Watcher(观察者)等来实现。

Observer()之所以能够监听数据变化,是因为它依靠了es6的Object.defineProperty(obj, prop, descriptor):

这个方法可以给对象添加或一个属性,并且返回这个对象,它有三个参数,前面两个obj、prop不多说了,重头戏是第三个参数descriptor,既描述对象,这个对象可以传configurable、enumerable、value...以及get、set

        function Observer(obj, vm) {
            Object.keys(obj).forEach(function(key) {
                Object.defineProperty(obj, key, {
                    get: function() {
                        return obj[key];
                    },
                    set: function(newVal) {
                        if (newVal === obj[key]) return;
                        obj[key] = newVal;
                    }
                });
            });
        }

这段代码的作用就是遍历obj的每个属性,加上get和set,读取obj属性的时候就会触发get,给obj属性赋值的时候就会触发set.

那Observer()怎么样才能在数据变更时及时通知到Dep,再有Dep去通知Watcher呢?看看Dep()代码:

 1         /**
 2          * 收集Watcher依赖并通知数据变更
 3          */
 4         function Dep () {
 5             this.subs = []
 6         }
 7         Dep.prototype = {
 8 
 9             // 添加订阅者
10             addSub: function(sub) {
11                 this.subs.push(sub);
12             },
13 // 通知订阅者 14 notify: function() { 15 this.subs.forEach(function(sub) { 16 sub.update(); 17 }); 18 } 19 };

改写下Observer():

扫描二维码关注公众号,回复: 10532626 查看本文章
 1         function observe (obj, vm) {
 2             Object.keys(obj).forEach(function (key) {
 3                 defineReactive(vm, key, obj[key]);
 4             });
 5         }
 6         function defineReactive (obj, key, val) {
 7             var dep = new Dep();
 8             Object.defineProperty(obj, key, {
 9                 get: function () {
10                     if (Dep.target) dep.addSub(Dep.target);
11                     return val
12                 },
13                 set: function (newVal) {
14                     if (newVal === val) return
15                     val = newVal;
16                     dep.notify();
17                 }
18             });
19         }
而Dep.target指的是Watcher:
 1         function Watcher(vm, cb, expOrFn) {
 2             //  this为Watcher构造函数
 3             Dep.target = this;
 4             this.cb = cb
 5             this.vm = vm
 6             this.expOrFn = expOrFn
 7             this.value = this.get()
 8             this.update();
 9             Dep.target = null;
10         }
11         Watcher.prototype = {
12             update: function () {
13                 this.run()
14             },
15             run: function () {
16                 const value = this.get()
17                 if (value !== this.value) {
18                     this.value = value
19                     this.cb.call(this.vm)
20                 }
21             },
22 
23             // 获取属性值
24             get: function () {
25                 this.value = this.vm[this.expOrFn];
26             }
27         }

由此可见:

  Oberver()通过Object.defineProperty()通知Dep(),而Dep()这里收集了Watcher依赖,当Dep()里有个订阅者的数组,全都是Watcher,当Oberver触发了Dep原型上的方法notify()的时候,就会触发Watcher去update,更新数据,而view层将进行render(),从而更新视图。

 

猜你喜欢

转载自www.cnblogs.com/caoshufang/p/12619292.html
今日推荐