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

要理解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. 牛客挑战赛46 B

    题目链接: 最小的指数 乍一看还以为是Pollard_rho算法,其实大可不必. 发现\(1<= n <= 1e18\),我们可以将n分为两部分(分块思想降低时间复杂度). 剔除小于等于\ ...

  2. java 系统属性设置

    一.语法: java -Dproperty=value 二.注意事项: value如果有空格,需用使用双引号如:java -Dfoo="some string" 三.常见使用地方: ...

  3. Java 一行代码 数组遍历输出

    Arrays.stream(arr).forEach(num -> System.out.println(num));

  4. html 08-HTML5详解(二)

    08-HTML5详解(二) #本文主要内容 拖拽 历史 地理位置 全屏 #拖拽 如上图所示,我们可以拖拽博客园网站里的图片和超链接. 在HTML5的规范中,我们可以通过为元素增加 draggable= ...

  5. AD PCB模块复用

    该文档为原创,转发需注明出处!https://www.cnblogs.com/brianblog/ 在画图的时候如果遇到PCB中有多个模块原理图是一模一样的时候,我们便会想能不能偷点懒,只画一个模块, ...

  6. 面试官问我:Object o = new Object() 占用了多少个字节?

    小小面试一下 前言蜜语 最近马师傅火的不要不要的,虽然没有抢到耗子尾汁的商标注册权,但是必须得蹭一波马师傅的热度,下面就是闪电五连鞭的教学环节,你准备好了吗! 在正式内容开始前先甩两篇关于类加载机制和 ...

  7. PHP连接数据库的方式

    1,旧的方式 - mysql(面向过程) 1 <?php 2 //定义连接参数 3 $host = 'localhost'; 4 $user = 'root'; 5 $password = '' ...

  8. 开发规范(一) 如何记录日志 By 阿里

  9. flowable流程启动时监听器

    一.核心配置类 package com.magus.project.flow.config; import com.google.common.collect.Maps; import com.mag ...

  10. spring mvc与mybatis与maven+mysql框架整合

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"% ...