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

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

 

Vue MVVM模型原理的更多相关文章

  1. 搞懂:MVVM模型以及VUE中的数据绑定数据劫持发布订阅模式

    搞懂:MVVM模式和Vue中的MVVM模式 MVVM MVVM : model - view - viewmodel的缩写,说都能直接说出来 model:模型,view:视图,view-Model:视 ...

  2. Vue学习之--------el与data的两种写法、MVVM模型、数据代理(2022/7/5)

    文章目录 1.el与data的两种写法 1.1.基础知识 1.2.代码实例 1.3.页面效果 2.MVVM模型 2.1. 基础知识 2.2 .代码实例 2.3.页面效果 3.数据代理 3.1. 基础知 ...

  3. Vue双向绑定原理,教你一步一步实现双向绑定

    当今前端天下以 Angular.React.vue 三足鼎立的局面,你不选择一个阵营基本上无法立足于前端,甚至是两个或者三个阵营都要选择,大势所趋. 所以我们要时刻保持好奇心,拥抱变化,只有在不断的变 ...

  4. vue双向绑定原理及实现

    vue双向绑定原理及实现 一.总结 一句话总结:vue中的双向绑定主要是通过发布者-订阅者模式来实现的 发布 订阅 1.单向绑定和双向绑定的区别是什么? model view 更新 单向绑定:mode ...

  5. Vue源码--解读vue响应式原理

    原文链接:https://geniuspeng.github.io/2018/01/05/vue-reactivity/ Vue的官方说明里有深入响应式原理这一节.在此官方也提到过: 当你把一个普通的 ...

  6. 直播课(1)如何通过数据劫持实现Vue(mvvm)框架

    19.6.28更新: 这篇博客比较完善:将每一部分都分装在单独的js文件中: 剖析Vue原理&实现双向绑定MVVM 半个月前看的直播课,现在才自己敲了一遍,罪过罪过 预览: 思路: 简单实现V ...

  7. MVC、MVP、MVVM模型

    在学习vue.react的过程中,总能看到MVVM模型,那么MVVM究竟是什么,下面将我最近看到的资料以及自己的想法总结一下. 与MVVM相似的,还有MVC.MVP,先从MVC.MVP这两个入手,方面 ...

  8. word2vec模型原理与实现

    word2vec是Google在2013年开源的一款将词表征为实数值向量的高效工具. gensim包提供了word2vec的python接口. word2vec采用了CBOW(Continuous B ...

  9. 【转】Select模型原理

    Select模型原理利用select函数,判断套接字上是否存在数据,或者能否向一个套接字写入数据.目的是防止应用程序在套接字处于锁定模式时,调用recv(或send)从没有数据的套接字上接收数据,被迫 ...

随机推荐

  1. Grafana 备份恢复教程

    原文链接:https://fuckcloudnative.io/posts/how-to-back-up-all-of-your-grafana-dashboards/ 目前我们 k8s 集群的 Gr ...

  2. securecrt7.1注册方法

    本文出自 "Kinslayer 's Blog" 博客,请务必保留此出处http://kinslayer.blog.51cto.com/3681810/833438

  3. js上 九.多分支语句

    9-3.if...else if ...else语句 多分支的if语句,多选一. 格式:

  4. IDEA的基本操作——导入导出jar包

    在使用Jmeter工具测试时,有时也需要导出jar包,测试对应功能,或者自己二次开发Jmeter工具,也是需要导出jar包的.既然经常用,所以就总结了下导入导出jar包的方法. 导入jar包 先打开i ...

  5. Java线程池二:线程池原理

    最近精读Netty源码,读到NioEventLoop部分的时候,发现对Java线程&线程池有些概念还有困惑, 所以深入总结一下 Java线程池一:线程基础 为什么需要使用线程池 Java线程映 ...

  6. Python爬取房天下二手房信息

    一.相关知识 BeautifulSoup4使用 python将信息写入csv import csv with open("11.csv","w") as csv ...

  7. win7激活不支持的启动引导分区完美解决方法

    前言: 激活win7显示不支持的启动引导分区怎么办?有用户使用暴风激活工具给win7 64位系统激活时,弹出Error提示框"不支持的启动引导分区". 这是因为传统的win7激活工 ...

  8. Windows系统提示:“windows找不到文件请确定文件名是否正确后

    最近使用Win7/10系统的用户反应在系统中移动了桌面上的一些与系统无关的文档,在挪动了文件之后出现的问题,弹出了windows找不到文件请确定文件名是否正确后,再试一次, 的错误提示,该怎么办呢? ...

  9. 安装篇五:安装MySQL(5.6.38版本)

    #1.MySQL安装 #1.准备环境 # No1:关闭:(iptables)selinux # No2:下载好安装包(这里使用 mysql-5.6.38.tar.gz 包安装) # No3:安装依赖包 ...

  10. [leetcode]75.Sort Color三指针

    import java.util.Arrays; /** * Given an array with n objects colored red,white or blue, * sort them ...