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(),从而更新视图。
Vue MVVM模型原理的更多相关文章
- 搞懂:MVVM模型以及VUE中的数据绑定数据劫持发布订阅模式
搞懂:MVVM模式和Vue中的MVVM模式 MVVM MVVM : model - view - viewmodel的缩写,说都能直接说出来 model:模型,view:视图,view-Model:视 ...
- 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. 基础知 ...
- Vue双向绑定原理,教你一步一步实现双向绑定
当今前端天下以 Angular.React.vue 三足鼎立的局面,你不选择一个阵营基本上无法立足于前端,甚至是两个或者三个阵营都要选择,大势所趋. 所以我们要时刻保持好奇心,拥抱变化,只有在不断的变 ...
- vue双向绑定原理及实现
vue双向绑定原理及实现 一.总结 一句话总结:vue中的双向绑定主要是通过发布者-订阅者模式来实现的 发布 订阅 1.单向绑定和双向绑定的区别是什么? model view 更新 单向绑定:mode ...
- Vue源码--解读vue响应式原理
原文链接:https://geniuspeng.github.io/2018/01/05/vue-reactivity/ Vue的官方说明里有深入响应式原理这一节.在此官方也提到过: 当你把一个普通的 ...
- 直播课(1)如何通过数据劫持实现Vue(mvvm)框架
19.6.28更新: 这篇博客比较完善:将每一部分都分装在单独的js文件中: 剖析Vue原理&实现双向绑定MVVM 半个月前看的直播课,现在才自己敲了一遍,罪过罪过 预览: 思路: 简单实现V ...
- MVC、MVP、MVVM模型
在学习vue.react的过程中,总能看到MVVM模型,那么MVVM究竟是什么,下面将我最近看到的资料以及自己的想法总结一下. 与MVVM相似的,还有MVC.MVP,先从MVC.MVP这两个入手,方面 ...
- word2vec模型原理与实现
word2vec是Google在2013年开源的一款将词表征为实数值向量的高效工具. gensim包提供了word2vec的python接口. word2vec采用了CBOW(Continuous B ...
- 【转】Select模型原理
Select模型原理利用select函数,判断套接字上是否存在数据,或者能否向一个套接字写入数据.目的是防止应用程序在套接字处于锁定模式时,调用recv(或send)从没有数据的套接字上接收数据,被迫 ...
随机推荐
- js处理浏览器兼容
1.try catch 在try中执行我们的代码,如果在执行的过程中发生了异常信息,我们在catch中写代替的执行方案 前提:不兼容四位情况下,执行对应的代码,需要发生异常错误才可以检测到 弊端:不 ...
- centos7安装Hive及其问题解决
本地如何安装hive (安装hive之前需要安装hadoop并启动hadoop的相关集群,mysql数据库) hadoop集群是两台,一台作为master,两台作为slaver,mysql单独占用一台 ...
- 说说 Python 中的高阶函数
高阶函数(higher-order function)指的是:接受一个函数为参数,或者把函数作为结果值返回的函数. 1 sorted() 比较常见的高阶函数是 sorted(),其内部的关键字参数 k ...
- 关于git中的merge和rebase
变基-git官网说明 变基 改变提交的基于分支 和merge不同 合并显示合并记录 变基合并更新后一起提交 不显示合并记录 变基 合并的结果是一致的
- idea中快捷键换成熟悉的celipse中快捷键
打开idea,找到菜单栏的file,点击打开,找到settings,打开 用key做关键词搜索keymap 找到之后点击打开,右侧就会显示快捷键界面,可以点击查看每一项 4 默认为defaul ...
- Java基础之String中equals,声明方式,等大总结
无论你是一个编程新手还是老手,提到String你肯定感觉特别熟悉,因为String类我们在学习java基础的时候就已经学过,但是String类型有我们想象的那么简单吗?其实不然,String类型的知识 ...
- 痞子衡嵌入式:MCUXpresso IDE下添加新路径下源文件进工程编译的方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下添加新路径下源文件进工程编译的方法. 接着上篇文章 <MCUXpresso IDE下SDK工程导入与 ...
- @component的作用详细介绍
最近项目要采用spring boot在学习的spring boot 的过程中第一次见到@component注解,特意在网上搜索下,摘录在此方便日后查阅. 1.@controller 控制器(注入服务) ...
- android基本组件 Button
android中提供了普通按钮Buttton和图片按钮ImageButton两种按钮组件,ImageButton按钮中主要有一个android:src属性,用于设置按钮的背景图片.可以在Button的 ...
- git基础-撤销操作
---恢复内容开始--- 撤销操作 在任何阶段,你都有可能想要撤销某些操作. 当我们提交完了代码,发现漏掉了几个文件没有添加,后者提交信息写错了,此时,可以运行--amend选项的提交命令尝试重新提交 ...