# Vue响应式原理解析
首先定义了四个核心的js文件
- 1. observer.js 观察者函数,用来设置data的get和set函数,并且把watcher存放在dep中
- 2. watcher.js 监听者函数,用来设置dep.target开启依赖收集的条件,和触发视图的更新函数
- 3. compile.js 编译者函数,用来编译模版和实例化 watcher 函数
- 4. index.js 入口文件
注意dep函数就是一个壳子,用来存放watcher和触发watcher更新的
首先从index.js开始,定义函数 SelfVue
```js
function SelfVue (options) {
Object.keys(this.data).forEach(function(key) {
self.proxyKeys(key);
//遍历data,给每一个key执行函数 proxyKeys,定义get、set
//这样就可以通过 this.name 来获取data中的name值了
//否则的话必须通过 this.data.name 才能获取
});
observe(this.data); //观察this.data,设置好各种监听的规则
new Compile(options.el, this);//在这里处理编译和调用watcher的函数
options.mounted.call(this); // 所有事情处理好后执行mounted函数
}
```
然后看 observe函数:
```js
defineReactive: function(data, key, val) {
var dep = new Dep();//初始化dep,dep用来存放watcher
Object.defineProperty(data, key, {
get: function getter () {
//只有在watcher中才会设置Dep.target,所以只有在watcher中才会去增加监听
if (Dep.target) {//Dep.target就是保存的Watcher自己
dep.addSub(Dep.target);
}
return val;
},
set: function setter (newVal) {
if (newVal === val) {
return;
}
val = newVal;
dep.notify();
}
});
}
```
然后看watcher
```js
function Watcher(vm, exp, cb) {
this.value = this.get(); // 将自己添加到订阅器的操作
/*
在这里执行this.get(),也就是调用了 this.vm.data[this.exp]
即调用了观察者中的get函数:
首先给Dep.target赋值,在观察者函数中,打开了
if (Dep.target) {
dep.addSub(Dep.target); //所以在这里可以向dep中添加watcher函数
}
*/
}
Watcher.prototype = {
get: function() {
Dep.target = this; // 缓存自己
var value = this.vm.data[this.exp] // 强制执行监听器里的get函数
Dep.target = null; // 添加到 dep 中之后,再释放自己
return value;
}
}
```
这样每次 new watcher的时候就会实例化watcher
然后就会调用this.value = this.get();
然后就会执行 this.vm.data[this.exp]
就会调用观察者函数中的 get方法,由于此时设置了dep.target
所以就会保存watcher到dep中
```js
new Watcher(this.vm, exp, function (value) {
self.updateText(node, value);
});
```
再来看compile.js中是何时触发监听watcher函数的,该文件做了三件事情:
```js
this.fragment = this.nodeToFragment(this.el); //获取挂载元素为代码片段
this.compileElement(this.fragment);//划分该代码片段的类型,执行编译
this.el.appendChild(this.fragment);//挂载该代码片段到html上
```
所以核心代码是compileElement函数:
```js
[].slice.call(childNodes).forEach(function(node) {
var reg = /\{\{(.*)\}\}/;
var text = node.textContent;
if (self.isElementNode(node)) { //v-model指令、v-on:click方法
self.compile(node);
} else if (self.isTextNode(node) && reg.test(text)) {//文本节点
self.compileText(node, reg.exec(text)[1]);
}
if (node.childNodes && node.childNodes.length) {//子节点继续循环遍历
self.compileElement(node);
}
});
```
循环遍历模板代码,按照:文本节点、v-model指令、v-on:click方法做不同的逻辑处理:
但是都会用到该函数
```js
new Watcher(this.vm, exp, function (value) {
self.updateText(node, value);
});
```
如上所述,实例化 Watcher的时候,就是给模板中用到的exp,向dep中增加watcher函数,
而watcher函数包括的方法:更新和get函数。
所以遍历完模板后,实例化 watcher,然后就会执行 watcher 中的get函数,实现监听功能。
```js
Watcher.prototype = {
update: function() {
var value = this.vm.data[this.exp];
var oldVal = this.value;
if (value !== oldVal) {
this.value = value;
this.cb.call(this.vm, value, oldVal);
}
},
get: function() {
Dep.target = this; // 缓存自己
var value = this.vm.data[this.exp] // 强制执行监听器里的get函数
Dep.target = null; // 释放自己
return value;
}
};
```
---
待数据发生变化时,会触发观察者函数中的 set 函数:
```js
set: function setter (newVal) {
if (newVal === val) {
return;
}
val = newVal;
dep.notify();
}
```
然后就会通知dep更新,这里注意的是,如果该值没有在模板中使用,this.sub就是空数组,所以这里通知函数中也不会更新视图:
```js
notify: function() {
//虽然上面data的所有值发生变化的时候会触发set和dep.notify();
//但是在这里只是会循环遍历每个之前监听到的watcher---this.subs
//所以,如果在html中没有用到的数据,即使在methods中使用到了
//在这里也不会触发视图更新
this.subs.forEach(function(sub) {
sub.update();
});
}
```
如果模板中使用了两次data中的title:
<h2>{{title}}</h2>
<h1>{{title}}</h1>
则对data循环后,针对title变量,有两个watcher,存在针对该data值:title的this.sub数组中。
所以如果没有在模板中使用到的data,比如age变量,
在set函数中,由于模板中没有用到-->则不会执行new Watcher-->则不会赋值给dep.target-->则不会给 dep中收集依赖,保存watcher;
在get函数中,由于模板中没有用到,对应的dep.sub数组中就是空数组。所以即使set函数通知了dep.notify函数,也会应为是空数组,导致不会执行循环,也无法触发watcher的更新视图函数

vue响应式原理解析的更多相关文章

  1. vue.js响应式原理解析与实现

    vue.js响应式原理解析与实现 从很久之前就已经接触过了angularjs了,当时就已经了解到,angularjs是通过脏检查来实现数据监测以及页面更新渲染.之后,再接触了vue.js,当时也一度很 ...

  2. 深度解析 Vue 响应式原理

    深度解析 Vue 响应式原理 该文章内容节选自团队的开源项目 InterviewMap.项目目前内容包含了 JS.网络.浏览器相关.性能优化.安全.框架.Git.数据结构.算法等内容,无论是基础还是进 ...

  3. 深入解析vue响应式原理

    摘要:本文主要通过结合vue官方文档及源码,对vue响应式原理进行深入分析. 1.定义 作为vue最独特的特性,响应式可以说是vue的灵魂了,表面上看就是数据发生变化后,对应的界面会重新渲染,那么响应 ...

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

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

  5. 详解Vue响应式原理

    摘要: 搞懂Vue响应式原理! 作者:浪里行舟 原文:深入浅出Vue响应式原理 Fundebug经授权转载,版权归原作者所有. 前言 Vue 最独特的特性之一,是其非侵入性的响应式系统.数据模型仅仅是 ...

  6. vue响应式原理,去掉优化,只看核心

    Vue响应式原理 作为写业务的码农,几乎不必知道原理.但是当你去找工作的时候,可是需要造原子弹的,什么都得知道一些才行.所以找工作之前可以先复习下,只要是关于vue的,必定会问响应式原理. 核心: / ...

  7. 深入Vue响应式原理

    深入Vue.js响应式原理 一.创建一个Vue应用 new Vue({ data() { return { name: 'yjh', }; }, router, store, render: h =& ...

  8. 浅析Vue响应式原理(三)

    Vue响应式原理之defineReactive defineReactive 不论如何,最终响应式数据都要通过defineReactive来实现,实际要借助ES5新增的Object.definePro ...

  9. 浅谈vue响应式原理及发布订阅模式和观察者模式

    一.Vue响应式原理 首先要了解几个概念: 数据响应式:数据模型仅仅是普通的Javascript对象,而我们修改数据时,视图会进行更新,避免了繁琐的DOM操作,提高开发效率. 双向绑定:数据改变,视图 ...

随机推荐

  1. 【笔试题】Java Data Types

    Java 知识测试 Java Data Types Question 1 Predict the output of the following program. class Test { publi ...

  2. Vue框架(一)——Vue导读、Vue实例(挂载点el、数据data、过滤器filters)、Vue指令(文本指令v-text、事件指令v-on、属性指令v-bind、表单指令v-model)

    Vue导读 1.Vue框架 vue是可以独立完成前后端分离式web项目的js框架 三大主流框架之一:Angular.React.Vue vue:结合其他框架优点.轻量级.中文API.数据驱动.双向绑定 ...

  3. 微信配置JS接口安全域名问题-Nginx配置

    1.将下载的txt文件放入/usr/local/nginx/html/目录下面. 2.修改nginx.cong配置文件中的location标签 location / { root html; inde ...

  4. python_socket (套接字)

    socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的. 网络上两个程序通过一个双向的通信连接实现数据的交换,这个连接 ...

  5. Java ClassLoader 学习理解

    /** * <html> * <body> * <P> Copyright 1994 JsonInternational</p> * <p> ...

  6. 2019 唯品会java面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.唯品会等公司offer,岗位是Java后端开发,因为发展原因最终选择去了唯品会,入职一年时间了,也成为了面试官 ...

  7. The XOR Largest Pair(tire树)

    题目 The XOR Largest Pair 解析 一年前听学长讲这道题,什么01trie,好高级啊,所以没学,现在一看.... 看到xor就应该想到二进制,一看数据\(A_i< 2^{31} ...

  8. 软件平台ThinkSNS+软件系统研发日记

    NO.1: 实用开源软件安装部署是第一步, ThinkSNS+响应快速安装,易于二开基准,为大家录制了一份宝塔面板安装社交系统ThinkSNS+视频教程,点开观看视频一起吸一吸. 若无法播放,请直接打 ...

  9. 【面试突击】- sql语句的优化分析

    开门见山,问题所在 原文地址:http://www.cnblogs.com/knowledgesea/p/3686105.html sql语句性能达不到你的要求,执行效率让你忍无可忍,一般会时下面几种 ...

  10. Unicode 字符和UTF编码的理解

    Unicode 编码的由来 我们都知道,计算机的内部全部是由二进制数字0, 1 组成的, 那么计算机就没有办法保存我们的文字, 这怎么行呢? 于是美国人就想了一个办法(计算机是由美国人发明的),也把文 ...