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

     
  • 相关阅读:
    Android开发教程
    Java基础——多线程
    Android基础总结(10)——手机多媒体的运用:通知、短信、相机、视频播放
    Android基础总结(9)——网络技术
    Android基础总结(7)——异步消息处理
    Android基础总结(6)——内容提供器
    《App研发录》知识点汇总
    Android基础总结(5)——数据存储,持久化技术
    Android基础总结(4)——广播接收器
    Android基础总结(3)——UI界面布局
  • 原文地址:https://www.cnblogs.com/caoshufang/p/12619292.html
Copyright © 2020-2023  润新知