vue的响应式原理

  当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter

Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在属性被访问和修改时通知变更。每个组件实例都对应一个 watcher 实例,它会在组件

渲染的过程中把“接触”过的数据属性记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

通过这么长时间的学习,我用比较直白的话来详细的解释一下原理

首先咱们需要掌握两个方法

一个是Object.defineProperty,一个是订阅者设计模式

Object.defineProperty方法

Object.defineProperty会直接在一个对象上定义一个新属性或者修改一个对象的现有属性,并且返回这个对象。

Object.defineProperty(obj,prop,descriptor)有三个属性。obj是要定义属性的对象。prop是需要定义或者修改的属性的名称,descrptor是被定义或修改的属性描述符。

setter或者getter是js对象中用来设置属性或获取属性的方法,他是在创建对象的时候指明的。

当data对象中有值存在时,vue就会获取这个对象,获取这个对象的时候就会调用get,然后会用Object.keys()方法拿到这个data对象中的每个属性,

然后进行遍历,得到每个属性,然后通过Object.defineProperty的set和get方法进行设置属性值或者是获取属性值。

发布-订阅模式

举个例子来说明一下发布者订阅者模式。上面的例子中,就是让张三和李四来订阅了这个message属性的改变。

发布-订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而

是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,

只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。

举一个例子,你在微博上关注了A,同时其他很多人也关注了A,那么当A发布动态的时候,微博就会为你们推送这条动态。

A就是发布者,你是订阅者,微博就是调度中心,你和A是没有直接的消息往来的,全是通过微博来协调的(你的关注,A的发布动态)。

vue就是通过这种发布者订阅者模式来处理响应式数据的。

下面的代码只是把整个响应式的过程解释了一下,但是源码并不是这么写的,但是整个流程是这样走滴,只不过我简化可很多~~希望大家能明白哈

  // 他们全用了message
  <div>{{message}}</div>
    <p>{{message}}</p>
    <i>{{message}}</i>
 
   data() {
      return {
      message:'嘻嘻',
        name:'why'

    }

 
    },       
 
      // data传进了new Vue里面。内部拿到了data'中的对象,嗯,就拿这个名字命名为obj把,        
       var obj={           
        message:'哈哈',     
          name:'why'          };
// 然后通过遍历obj这个对象拿到这个属性------
      // Object.keys(obj)返回的是一个数组形式的这个对象的属性
// key代表的是每个属性
Object.keys(obj).forEach(key => {
// 拿到这个属性
let value=obj[key]
Object.defineProperty(obj,key,{
        // 设置属性
set(newValue) {
// 可以在这个位置监听key的改变
value=newValue
  
        // dep.notify() 然后在类似这个地方通知订阅者发生改变
          <!--  发生改变的时候,需要获取到谁在用这个值,假如这里有俩个人在用张三和李四,此时就需要对每个用到message进行解析,
          根据解析html代码,来获取到哪些人在用这些属性,他在获取message里的
          值的时候,他会调用一下get方法,谁用这个message,谁都会调取一次get,到时候就能知道到底是谁调用了这个message,
          一旦newValue发生改变,就会通知这三个人,然后会通知这三个人,让这三个人把界面更新一下 get方法---自身的update方法
          这时候就需要用发布订阅者模式来监听,让这三个人订阅这个属性的改变-->
                  console.log('监听'+key+'改变'+':'+value)
},
get() {
            在类似这个的地方创建一个watch的对象。来获取每个订阅者
            // const wat1=new Watcher('涵涵');
             console.log('获取'+key+'对应的值')
            return value
}
})
})
// 他就会执行对象里的set属性,把他的名字设置成'hanhan'
obj.name='hanhan'

我们把多个订阅者对象添加到发布者里面,一旦值发生改变,发布者只要去调用了自己的notify,就会立马通知之前所有的订阅者,

订阅者是一个数组,遍历数组里的每个成员,数组里面每个成员都有watch,通知订阅者去更新自己的update。然后进行更新界面

          // 发布者
class Dep {
constructor() {
// 订阅了一个数组,用这个数组去记录所有的订阅者
this.subscription=[]
}
// 加入订阅者,加进去这个人,也就是张三李四,这两个人
addSub(watch) {
this.subscription.push(watch)
};
notify() {
this.subscription.forEach(item=>{
// 调用它自己的unpate去更新
item.update()
})
}
} // 观察者,用于监听观察,通过这个类创建对象,
// 订阅者
class Watcher {
constructor(name) {
this.name=name;
} update() {
// 把自己的内容进行更新
console.log(this.name+'发生update')
}
} // 实例一个dep对象
const dep=new Dep(); const wat1=new Watcher('张三');
dep.addSub(wat1) //张三就被订阅者放到了subscription的数组里面 const wat2=new Watcher('李四');
dep.addSub(wat1) //李四就被订阅者放到了subscription的数组里面 dep.notify()//这里定义notify,那么刚才的两个订阅者,就全被我通知到了
}

下面我用一张图对上面的内容进行一个总结吧,总结的比较肤浅,都是表面的知识,希望大家多多指点,一块进步哈。

observer主要是对data对象中的数据进行了劫持监听,利用Object.defineProperty,一个属性对应一个dep对象,name有一个dep对象,age有一个dep对象,

他们是一一对应的关系,每个dep对象里面都 有他的观察者对象,观察者1,观察者2...当属性值发生变化的时候就会去调用dep中的notify,通知watcher,利用watcher去更新视图。

当el传进complie里面时,主要是做了两件事

一是解析html,创建对应的watcher,放到对应的observer中的dep对象中去,具体怎么放得,上面有说哈,

二是他还会根据el中的内容初始化view,也就是解析咱们的{{message}},在界面中显示出  “嘻嘻”。

假如我们把name中的属性值改成了 '哈哈 ',那么observer中的Object.defineProperty立马会监听到值的改变,调用notify的方法,遍历watcher,进行update,然后更新视图,把 why 变为 “哈哈”

分享就到这里了哈,楼楼有说的不好的地方,希望大家多多指点哈~~

vue学习之深入响应式原理的更多相关文章

  1. 《Vue 进阶系列之响应式原理及实现》

    https://www.bilibili.com/video/av51444410/?p=5 https://github.com/amandakelake/blog/issues/63 https: ...

  2. Vue.js学习 Item12 – 内部响应式原理探究

    深入响应式原理 大部分的基础内容我们已经讲到了,现在讲点底层内容.Vue.js 最显著的一个功能是响应系统 —— 模型只是普通对象,修改它则更新视图.这让状态管理非常简单且直观,不过理解它的原理也很重 ...

  3. vue 数组 新增元素 响应式原理 7种方法

    1.问题 思考一个问题,以下代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  4. Vue.js 技术揭秘(学习) 深入响应式原理 nextTick外传

    microTask  mutationObserve. promise.then macroTask setImmediate. messageChannnel.setTimeout.postMess ...

  5. vue进阶用法-深入响应式原理

    异步更新队列 当vue异步执行更新DOM时,只要观察到数据变化,vue经开启一个队列,并缓冲在同一时间循环中发生的所有数据改变.如果同一个watch被多次触发,只会一次推入到队列中.然后在下一个事件循 ...

  6. 【Vue源码学习】响应式原理探秘

    最近准备开启Vue的源码学习,并且每一个Vue的重要知识点都会记录下来.我们知道Vue的核心理念是数据驱动视图,所有操作都只需要在数据层做处理,不必关心视图层的操作.这里先来学习Vue的响应式原理,V ...

  7. Vue.js响应式原理

      写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出. 文章的原地址:answershuto/learnV ...

  8. 深入浅出Vue基于“依赖收集”的响应式原理(转)

    add by zhj: 文章写的很通俗易懂,明白了Object.defineProperty的用法 原文:https://zhuanlan.zhihu.com/p/29318017 每当问到VueJS ...

  9. 深入解析vue.js响应式原理与实现

    vue.js响应式原理解析与实现.angularjs是通过脏检查来实现数据监测以及页面更新渲染.之后,再接触了vue.js,当时也一度很好奇vue.js是如何监测数据更新并且重新渲染页面.vue.js ...

随机推荐

  1. windows下 python 如何安装pygame模块

    本机系统:win7,Pyhon版本: 3.6.0 1. 安装下载python官网 https://www.python.org/ 下载地址 https://www.python.org/downloa ...

  2. 基于hash和pushState的网页前端路由实现

    客户端路由 对于客户端(通常为浏览器)来说,路由的映射函数通常是进行一些DOM的显示和隐藏操作.这样,当访问不同的路径的时候,会显示不同的页面组件.客户端路由最常见的有以下两种实现方案:* 基于Has ...

  3. 夯实Java基础系列23:一文读懂继承、封装、多态的底层实现原理

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  4. 你所不知道的TIME_WAIT和CLOSE_WAIT

    你遇到过TIME_WAIT的问题吗? 我相信很多都遇到过这个问题.一旦有用户在喊:网络变慢了.第一件事情就是,netstat -a | grep TIME_WAIT | wc -l 一下.哎呀妈呀,几 ...

  5. Solidity 编程实例--简单的公开拍卖

    通常简单的公开拍卖合约,是每个人可以在拍卖期间发送他们的竞拍出价.为了实现绑定竞拍人的到他们的拍卖,竞拍包括发送金额/ether.如果产生了新的最高竞拍价,前一个最高价竞拍人将会拿回他的钱.在竞拍阶段 ...

  6. 从零开始入门 K8s | 可观测性:监控与日志

    作者 | 莫源  阿里巴巴技术专家 一.背景 监控和日志是大型分布式系统的重要基础设施,监控可以帮助开发者查看系统的运行状态,而日志可以协助问题的排查和诊断. 在 Kubernetes 中,监控和日志 ...

  7. C#学习--Oracle数据库基本操作(连接、增、删、改、查)封装

    写在前面: SQLserver的C#封装:https://www.cnblogs.com/mexihq/p/11636785.html 类似于上篇有关SQLserver的C#封装,小编对Oracle数 ...

  8. LeetCode 300. Longest Increasing Subsequence最长上升子序列 (C++/Java)

    题目: Given an unsorted array of integers, find the length of longest increasing subsequence. Example: ...

  9. vue+element 实现商品sku效果

    在网上搜索了很久,没有发现合适sku编辑的文章,只能自己写一个vue+element 的sku编辑功能.实现的效果如下图 除成本.售价.库存.货号这几个写死的属性外,可自行添加/删除商品属性,自行添加 ...

  10. 使用mongoose-paginate-v2查询缓慢问题

    场景 mongoose-paginate-v2 是一个mongoose上的分页插件,我也用过很多次了,但是最近在创建项目遇到了问题. 老代码中不使用分页插件进行查询,然后自己使用中间件进行分页 old ...