zoukankan      html  css  js  c++  java
  • Vue MVVM模型原理

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

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

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

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

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

    具体关于Object.defineProperty()的属性,可见MDN的Object.defineProperty()

    这个方法可以给对象添加或一个属性,并且返回这个对象,它有三个参数,前面两个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():

     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(),从而更新视图。

     
  • 相关阅读:
    C# 从服务器下载文件
    不能使用联机NuGet 程序包
    NPOI之Excel——合并单元格、设置样式、输入公式
    jquery hover事件中 fadeIn和fadeOut 效果不能及时停止
    UVA 10519 !! Really Strange !!
    UVA 10359 Tiling
    UVA 10940 Throwing cards away II
    UVA 10079 Pizze Cutting
    UVA 763 Fibinary Numbers
    UVA 10229 Modular Fibonacci
  • 原文地址:https://www.cnblogs.com/caoshufang/p/12619292.html
Copyright © 2011-2022 走看看