注意:
响应式原理和双向数据绑定原理是两回事,一般面试官会先问响应式原理再问双向数据绑定的原理
详细文章

1.响应式原理

核心是数据劫持和依赖收集,是通过数据劫持结合发布者-订阅者模式的方式来实现的。通过Object.defineProperty()为对象添加属性,然后为对象设置getter和setter方法,之后我们每次通过点语法获取属性就会执行getter方法,在这个方法中我们会把调用 此属性的依赖收集到一个集合中;而在我们给属性赋值(修改属性)时,会触发setter方法,然后去通知集合中的依赖更新,做到数据变更 驱动视图变更。

Object.defineProperty(obj, key, {// writable:true,// 可写// enumerable: true, // 可枚举// configurable: true, //可删除//拦截get,当我们访问data.key时会被这个方法拦截到get () {//我们在这里收集依赖return obj[key];},//拦截set,当我们为data.key赋值时会被这个方法拦截到set (newVal) {//当数据变更时,通知依赖项变更UI}
})

2. MVVM模式

MVVM框架的的核心就是双向绑定, 其原理是通过数据劫持+发布订阅模式相结合的方式来实现的,简单来说就是数据层发生变化的时候,可同步更新视图层,当视图层发生变化的时候,同步更新数据层

  • MVVM将数据双向绑定作为核心思想,View 和 Model之间没有联系,他们通过ViewModel这个桥梁进行交互
  • Model 和 ViewModel 之间的交互是双向的,因此View 的变化会自动同步到Model,而Model的变化也会立即反映到View上显示
  • 当用户操作View , ViewModel 感知到变化,然后通知Model发生相应改变;反之当Model发生改变,ViewModel也能感知到变化,使View作出相应更新

3. 如何实现?

Vue 类

首先我们实现一个 Vue 类,用于创建 vue对象,它的构造方法接收一个options参数,用于初始化vue

class Vue {constructor(options){this.$el = options.el;this._data = options.data;this.$data = this._data// 对data进行响应式处理new Observe(this._data)}
}// 创建 vue 对象
new Vue ({el:'#app',data:{message:'hello world'}
})

上面的代码中我们首先创建了一个Vue的类,构造函数跟我们平时使用的Vue大致一致,为了容易理解我们这里只处理了参数el和data。
我们发现构造函数的最后一行创建了一个Observe类的对象,并传入data作为参数,这里的Observe就是对data数据进行响应式处理的类,接下来我们看一下Observe类的简单实现。

Observe类

(数据监听器:能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者)

我们在Oberve类中实现对data的监听,就是通过Object.defineProperty()方法实现的数据劫持,代码如下:

class Observe {constructor(data){// 如果传入的数据是objectif(typeof data == 'object'){this.walk(data);}}// 这个方法遍历对象中的属性,并依次对其进行响应式处理walk(obj){// 获取所有属性const keys = Object.keys(obj);for ( let i = 0; i < keys.length; i++ ){// 对所有属性进行监听(数据劫持)this.defineReactive(obj,keys[i])}}defineReactive(obj,key){if (typeof obj[key] == 'object'){// 如果属性是对象,那么递归调用walk方法this.walk(obj[key]);}const dep = new Dep(); // Dep类用于收集依赖const val = obj[key];Object.defineProperty(obj,key,{enumerable:true,configurable:true,// get代理将Dep.target 即watcher对象添加到依赖集合中get(){// 这里在创建watcher对象时 会给Dep.target赋值if(Dep.target){dep.addSubs(Dep.target);}return val;},set(newVal){val = newVal;// 依赖的变更响应dep.notify(newVal);}})}
}

上述代码中我们使用到了Dep类,我们在劫持到的数据的get方法中收集到的依赖会被放到Dep类中保存。

Dep类

订阅器:订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observe 和 订阅者 Watcher 进行统一管理。

下面代码是Dep类的实现,他有一个subs的数组,用于保存依赖,这里的依赖是我们后面要定义的Watcher,Watcher即观察者

class Dep (){static target = nullconstructor(){this.subs=[];}addSubs(watcher){this.subs.push(watcher)}notify(newVal){for(let i = 0; i < this.subs.length; i++){this.subs[i].update(newVal);  }}
}

Watcher类

作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

观察者类,它做的事情就是观察数据的变更,它会调用data中对应属性的get方法触发依赖收集,并在数据变更后执行相应的更新

let uid = 0;
class Watcher{// vm即一个vue对象,key要观察的属性,cb是观测到数据变化后需要做的操作,通常是指dom变更constructor(vm,key,cb){this.vm = vm;this.uid = uid++;this.cb = cb;// 调用get触发依赖收集之前,把自身赋值给Dep.taget静态变量Dep.target=this;// 触发对象上代理的get方法,执行get添加依赖this.value=vm.$data[key];//用完即清空Dep.target=null;}// 在调用set触发Dep的notify时要执行的update函数,用于响应数据变化执行run函数即dom变更update(newVal){// 值发生变化才变更if(this.value !== newVal){this.value = newVal;this.run()}}// 执行DOM更新等操作run(){this.cb(this.value);}
}

通过以上的代码我们就实现了一个去除了模板编译的简易版的Vue,我们用简单化模拟dom的变更

//======测试=======
let data={message:'hello',num:0
}
let app=new Vue({data:data
});
//模拟数据监听
new Watcher(app,'message',function(value){//模拟dom变更console.log('message 引起的dom变更--->',value); // world
})
new Watcher(app,'num',function(value){//模拟dom变更console.log('num 引起的dom变更--->',value); // 100
})
data.message='world';
data.num=100;

总结

1、实现一个监听器 Observe:对数据对象进行遍历,包括子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变化。并且可以拿到最新值通知订阅者。

2、实现一个订阅者 Watcher:Watcher 订阅者是 Observe 和 Compile 之间通信的桥梁 ,主要的任务是订阅 Observe 中的属性值变化的消息,当收到属性值变化的消息时,触发解析器 Compile 中对应的更新函数。

3、实现一个解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,调用更新函数进行数据更新。

4、实现一个订阅器 Dep:订阅器采用 发布-订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行统一管理。

vue2 Object.definProperty响应式原理(面试题)相关推荐

  1. vue2和vue3响应式原理

    vue2响应式原理:核心使用Object.defineProperty给属性定义get和set方法 注意:对象的多次递归,针对数组需要重写数组方法 函数劫持:把函数内部进行重写同时继续调用老的方法,在 ...

  2. Vue2.0 —— 由设计模式切入,实现响应式原理

    Vue2.0 -- 由设计模式切入,实现响应式原理 <工欲善其事,必先利其器> 既然点进来了,麻烦你看下去,希望你有不一样的收获. 大家好,我是vk,好久不见,今天我们一起来盘一盘关于 V ...

  3. arduinowifi.send怎么获取响应_Vue3.0 响应式原理 (一)

    前几天,回顾整理下关于vue2.0的响应式原理.温故而知新么,那么今天,整理了一下关于vue3.0的响应式原理,利用 JavaScript 来写的.本着尽可能的清晰易懂的原则,所以,可能会分几篇文章来 ...

  4. Vue响应式原理 vue源码(十一)

    前言 看过很多讲响应式的文章,大多都是告诉你们,有Observer,Dep,Wathcer类,Object.definePorperty,先会触发get中的dep.depend收集依赖,然后数据改变时 ...

  5. 【Vue3中的响应式原理】

    Vue3响应式原理 在Vue2的响应式中,存在着新增属性,删除属性以及直接通过下标修改数组,但页面不会自动更新的问题.但是在Vue3中,这些问题都得以解决. Vue2中的响应式原理 首先我们先看一下V ...

  6. javascript --- vue2.x中原型的使用(拦截数组方法) 响应式原理(部分)

    说明 在Vue2.x中,利用了对原型链的理解,巧妙的利用JavaScript中的原型链,实现了数组的pop.push.shift.unshift.reverse.sort.splice等的拦截. 你可 ...

  7. Vue2的响应式原理

    --------Vue2响应式原理---------- 原理:通过数据劫持 defineProperty + 发布订阅者模式,当 vue 实例初始化后 observer 会针对实例中的 data 中的 ...

  8. Day 05- Vue3 Vue2响应式原理

    Vue2的响应式 核心:通过 Object.defineProtytype() 对对象的已有属性值的读取和修改进行劫持: 数据劫持  --> 给对象扩展属性 -->  属性设置 实现原理: ...

  9. vue2响应式原理解析并实现一个简单响应系统

    vue2响应式原理 Object.defineProperty() 要理解 vue2 数据响应式原理,我们首先要了解Object.defineProperty()方法.下面这些概念引自MDN. Obj ...

最新文章

  1. PHP 格式化文件大小
  2. Linux下取代top的进程管理工具 htop
  3. smoteenn算法_类别不平衡问题之SMOTE算法(Python imblearn极简实现)
  4. 数据库还原失败System.Data.SqlClient.SqlError: 无法执行 BACKUP LOG,因为当前没有数据库备份...
  5. linux内核 漏洞扫描,Linux kernel中存在15年的漏洞
  6. 算法与面试之-如何准备算法面试
  7. XnSay机器人授权系统源码
  8. 使用集搜客爬取酷狗排行歌曲信息
  9. 晨哥真有料丨你太容易被得到了!
  10. 【报告分享】2020中国消费市场发展报告.pdf(附下载链接)
  11. python基础函数及用法意思_Python基础之函数基本用法与进阶详解
  12. GNU/Linux下的开发环境
  13. 如何让普通用户执行一些root用户才能执行的命令
  14. php 汉字unico编码范围,汉字 Unicode 编码范围
  15. WinRar注册机或注册码
  16. SmartUpload问题
  17. Win10 激活工具被删除或“无法成功完成操作,因为文件包含病毒或潜在的垃圾软件”
  18. 计算机期刊在线阅读,2010年计算机领域SCI收录期刊
  19. Golang语言移植-ARM开发环境搭建
  20. Python - 使用ffmepg批量转换某个文件夹以及所有子文件夹下所有的视频,修改其帧率/码率/分辨率到另一文件夹,并保留原有文件夹结构

热门文章

  1. MVC架构 使用FastReport
  2. 安卓一键清理内存_垃圾一键清理大师软件下载-垃圾一键清理大师下载v3.2.2 安卓版...
  3. 怎么将pdf转换为cad格式呢?
  4. 职场上,这些不为人知的潜规则,你知道吗?
  5. bat脚本自定义魔兽warIII运行分辨率,去黑边
  6. 【在JS中如何获取图片路径以及更改图片】
  7. 绩效管理软件哪个好?企业如何建立绩效考核体系?
  8. 不定积分24个基本公式_干货丨语文阅读理解的24个万能公式,背熟6年一分不扣...
  9. 官方不支持,我来支持,autojs支持db操作
  10. uniapp实现抽奖功能