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

从很久之前就已经接触过了angularjs了,当时就已经了解到,angularjs是通过脏检查来实现数据监测以及页面更新渲染。之后,再接触了vue.js,当时也一度很好奇vue.js是如何监测数据更新并且重新渲染页面。今天,就我们就来一步步解析vue.js响应式的原理,并且来实现一个简单的demo。

首先,先让我们来了解一些基础知识。

基础知识

Object.defineProperty

es5新增了Object.defineProperty这个api,它可以允许我们为对象的属性来设定getter和setter,从而我们可以劫持用户对对象属性的取值和赋值。比如以下代码:

const obj = {};

let val =  'cjg';
Object.defineProperty(obj, 'name', {
get () {
console.log('取值操作')
return val
  },
  set (newVal) {
    console.log('fu值操作')
val = newVal
  }
})
console.log(obj.name)
obj.name = 'zfj'
console.log(obj.name)
我们通过Object.defineProperty劫持了obj[name]的取值和赋值操作,因此我们就可以在这里做一些手脚啦,比如说,我们可以在obj[name]被赋值的时候触发更新页面操作。

 

发布订阅模式

发布订阅模式是设计模式中比较常见的一种,其中有两个角色:发布者和订阅者。多个订阅者可以向同一发布者订阅一个事件,当事件发生的时候,发布者通知所有订阅该事件的订阅者。我们来看一个例子了解下。

class Dep {
constructor () {
this.subs = [];
};
//添加订阅
addSub (sub) {
debugger
if(this.subs.indexOf(sub) < 0) {
this.subs.push (sub)
}
};
//通知订阅者
notify () {
this.subs.forEach((subs)=>{
sub.updata();
})
};
};
const dep = new Dep();
const sub = {
updata () {
console.log('sub1 updata');
}
};
const sub1 = {
updata () {
console.log('sub2 updata');
}
};
dep.addSub(sub);
dep.addSub(sub1);
dep.notify();

 

动手实践

我们了解了Object.defineProperty和发布订阅者模式后,我们不难可以想到,vue.js是基于以上两者来实现数据监听的。

  1. vue.js首先通过Object.defineProperty来对要监听的数据进行getter和setter劫持,当数据的属性被赋值/取值的时候,vue.js就可以察觉到并做相应的处理。

  2. 通过订阅发布模式,我们可以为对象的每个属性都创建一个发布者,当有其他订阅者依赖于这个属性的时候,则将订阅者加入到发布者的队列中。利用Object.defineProperty的数据劫持,在属性的setter调用的时候,该属性的发布者通知所有订阅者更新内容。

接下来,我们来动手实现(详情可以看注释):

//实践检测一组数据
let data = {
name: 'cba',
obj:{
age:123
}
}
//定义观察者服务
class observer {
constructor(){
if(!data || typeof data !== 'object') {
return
}
this.data = data
this.walk()
}
//对传入数据进行劫持
walk(){
for(let key in this.data){
this.defineRactive(this.data, key, this.data[key])
}
}
//为属性注册发布者
defineRactive(obj,key,val){
//定义发布者
let dep = new Dep()
//如果属性值为Object继续劫持,层层递归
new observer(val) Object.defineProperty(obj,key,{
get(){
if(Dep.target){
dep.addSub(Dep.target)
}
return val
},
set(newVal){
if(val === newVal){
return
}
new observer(newVal)
dep.notify()
}
})
}
} class Dep {
constructor(){
this.subs = []
}
addSub(sub){
if(this.subs.indexOf(sub) < 0){
this.subs.push(sub)
}
}
notify(){
this.subs.forEach((sub)=>{
sub.upadta()
})
}
}
Dep.target = null
class watch {
constructor(vm, key, updataCb){
this.vm = vm
this.key = key
this.updataCb = updataCb
this.value = null
this.get()
}
get(){
Dep.target = this
let keys = this.keys.split('.')
let value = this.vm
keys.forEach((_key)=>{
value = value[_key]
})
this.value = value
Dep.target = null
return this.value
}
updata(){
let oldValue = this.value
let newValue = this.get()
this.updataCb(oldValue,newValue)
}
} new observer(data)
new watch(data,'name',(a,b)=>{
console.log(a,b)
})

vue.js响应式原理解析与实现的更多相关文章

  1. vue.js响应式原理解析与实现—实现v-model与{{}}指令

    上一节我们已经分析了vue.js是通过Object.defineProperty以及发布订阅模式来进行数据劫持和监听,并且实现了一个简单的demo.今天,我们就基于上一节的代码,来实现一个MVVM类, ...

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

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

  3. Vue.js响应式原理

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

  4. Vue.js 响应式原理

    1. Vue2.x 基于 Object.defineProperty 方法实现响应式(Vue3 将采用 Proxy) Object.defineProperty(obj, prop, descript ...

  5. vue响应式原理解析

    # Vue响应式原理解析 首先定义了四个核心的js文件 - 1. observer.js 观察者函数,用来设置data的get和set函数,并且把watcher存放在dep中 - 2. watcher ...

  6. vue深入响应式原理

    vue深入响应式原理 深入响应式原理 — Vue.jshttps://cn.vuejs.org/v2/guide/reactivity.html 注意:这里说的响应式不是bootsharp那种前端UI ...

  7. Vue 数据响应式原理

    Vue 数据响应式原理 Vue.js 的核心包括一套“响应式系统”.“响应式”,是指当数据改变后,Vue 会通知到使用该数据的代码.例如,视图渲染中使用了数据,数据改变后,视图也会自动更新. 举个简单 ...

  8. Vue的响应式原理

    Vue的响应式原理 一.响应式的底层实现 1.Vue与MVVM Vue是一个 MVVM框架,其各层的对应关系如下 View层:在Vue中是绑定dom对象的HTML ViewModel层:在Vue中是实 ...

  9. 一探 Vue 数据响应式原理

    一探 Vue 数据响应式原理 本文写于 2020 年 8 月 5 日 相信在很多新人第一次使用 Vue 这种框架的时候,就会被其修改数据便自动更新视图的操作所震撼. Vue 的文档中也这么写道: Vu ...

随机推荐

  1. django-debug-toolbar 安装及配置 django性能监控及调试

    安装: pip install django-debug-toolbar 配置: settings 配置 DEBUG = True INSTALLED_APPS = [ 'debug_toolbar' ...

  2. Spring-Cloud-Netflix

    Spring Cloud Netflix组件以及部署 (1)Eureka,服务注册和发现,它提供了一个服务注册中心.服务发现的客户端,还有一个方便的查看所有注册的服务的界面. 所有的服务使用Eurek ...

  3. creator Box2d的相关物理问题

      项目的屏幕配置为 1152*640,没有对这个数值调整来测试质量的除数1024会不会变化 m = h * w / 1024 (m 质量,h 物体高度,w 物体宽度) g = 0, -320 ( ( ...

  4. 为什么要学习socket

    为什么要学习socket socket历史悠久.它们的使用始于 1971年的ARPANET,后来成为1983年发布的Berkeley Software Distribution(BSD)操作系统中的A ...

  5. Python error: Microsoft Visual C++ 9.0 is required (Unable to find vcvarsall.bat)解决方案

    error: Microsoft Visual C++ 9.0 is required (Unable to find vcvarsall.bat). Get it - 解决方案 python通过pi ...

  6. HBASE基础知识总结

    HBASE基础知识总结 一,概要说明 文章首先回顾HBase 的数据模型和数据层级结构,对数据的每个层级的作用和架构进行了详细阐述:随后介绍了数据写入和读取的详细流程.先把架构图和流程图来坐镇. 架构 ...

  7. Ansible 批量修改密码

    客户要求每3个月修改一次主机密码.密码规则为客服提供的一串字符 xxxx + 主机后3位. 将需要登录主机添加到 Ansible. 将需要登录主机的公钥添加到 known_hosts ssh-keys ...

  8. Python之print()函数

    1. 输出字符串 >>> str = 'Hello World' >>> print (str) Hello World 2. 格式化输出整数 支持参数格式化 &g ...

  9. Bus Hound抓包分析,基于HID设备(原创)

    Bus Hound数据分析: CTL:表示8字节的USB控制传输的Setup包----------------------------重点分析 控制传输setup(token包)和对应数据包(DATA ...

  10. html中radio单选和文本框限制只能输入数字的解决方案

    一.当html中存在多个radio单选按钮时将所有的单选按钮name属性设置为一样,就可实现每次只选中一个的效果. 二.限制文本框只能输入数字,代码如下: $(function(){ $(" ...