浅谈vue响应式原理及发布订阅模式和观察者模式
一.Vue响应式原理
首先要了解几个概念:
数据响应式:数据模型仅仅是普通的Javascript对象,而我们修改数据时,视图会进行更新,避免了繁琐的DOM操作,提高开发效率。
双向绑定:数据改变,视图改变,数据也随之改变,我们可以使用v-model在表单上创建双向数据绑定。
数据驱动是Vue最独特的特性之一:开发过程中仅需要关注数据本身,不需要关心数据是如何渲染到视图。
vue2.X中的响应式原理是基于defineProperty,兼容IE8以上版本,核心原理代码如下:
let data={
msg:'hello',
count:10
}
let vm={}
proxyData(data)
function proxyData(data){
Object.keys(data).forEach(key=>{
Object.defineProperty(vm,key,{
enumerable:true,
configurable:true,
writeable:true,
//获取值的时候执行
get(){
console.log('get:',key,data[key])
return data[key]
},
//设置值的时候执行
set(newValue){
data[key]=newValue
console.log('set:',key,newValue)
document.querySelector('#app').textContent=data[key]
}
})
})
}
vm.msg //获取(get方法) hello
vm.msg='hello World' //设置新属性值并渲染到页面(set方法)
vm.msg //hello World
vue3.X中的响应式原理是基于Proxy,直接监听对象,而非属性,ES6中新增,IE不支持,性能由浏览器优化,性能比defineProperty要好,代码的话相比较defineProperty要简洁一些,对于多个属性的值不需要进行循环遍历处理。
let data={
msg:'hello',
count:0
}
//模拟 Vue 实例
let vm=new Proxy(data,{
//执行代理行为的函数
//当访问 vm 的成员会执行
get(target,key){
console.log('get,key:',key,target[key])
return target[key]
},
set(target,key,newValue){
console.log('set,key:',key,newValue)
if(target[key] === newValue){
return
}
target[key]=newValue
document.querySelector("#app").textContent=target[key]
}
})
//测试
vm.msg='Hello World'
console.log(vm.msg)
二.发布订阅模式和观察者模式
1.发布/订阅模式
这个概念有些抽象,下面举个例子说明下,家长比较关心孩子成绩,天天问孩子成绩出来没,假设可以到孩子所在班级去订阅孩子成绩,一旦考试成绩出来,相当于触发了一个事件,最后有班级的老师以短信的形式通知给家长,
不需要天天问孩子成绩出来没,家长就是事件的订阅者,老师是事件的发布者,孩子所在的班级可以假想成一个事件的中心。vue中的自定义事件都是基于发布/订阅模式的。下面模拟下发布订阅模式的运行机制:
//事件触发器
class EventEmitter(){
constructor(){
// 初始化对象{ 'click':[fn1,fn2],'change':[fn] }
this.subs=Object.create(null)
}
//注册事件
$on(eventType,handler){
this.subs[eventType] = this.subs[eventType] || []
this.subs[eventType].push(handler)
}
//触发事件
$emit(eventType){
if(this.subs[eventType]){
this.subs[eventType].forEach(handler => {
handler()
})
}
}
}
//测试 let em =new EventEmitter() em.$on('click',()=>{
console.log('click1')
})
em.$on('click',()=>{
console.log('click2')
})
em.$emit('click') //打印结果 click1,click2
二.观察者模式
观察者模式和订阅模式的区别是没有事件中心,只有发布者和订阅者,并且发布者需要知道订阅者的存在.
概念:
观察者 --Watcher
update():当事件发生时,具体要做的事情。
发布者 --Dep
subs数组:存储所有的观察者
addSub():添加观察者
notify():当事件发生,调用所有观察者的update()方法
//发布者-目标
class Dep{
constructor() {
//记录所有的订阅者
this.subs=[]
}
//添加订阅者
addsub(sub){
if(sub && sub.update){
this.subs.push(sub)
}
}
//发布通知
notify(){
this.subs.forEach(sub=>{
sub.update()
})
}
}
//订阅者-观察者
class Watcher{
update(){
console.log('update')
}
}
//测试
let dep=new Dep()
let watcher=new Watcher()
dep.addsub(watcher)
dep.notify() //打印结果 update
总结:
观察者模式是由具体目标调度,比如当事件触发,Dep就会去调用观察者的方法,所以观察者的订阅者和发布者之间是存在依赖的。
发布订阅模式由统一调度中心调用,因此发布者和订阅者不需要知道对方的存在。

浅谈vue响应式原理及发布订阅模式和观察者模式的更多相关文章
- 浅谈Vue响应式(数组变异方法)
很多初使用Vue的同学会发现,在改变数组的值的时候,值确实是改变了,但是视图却无动于衷,果然是因为数组太高冷了吗? 查看官方文档才发现,不是女神太高冷,而是你没用对方法. 看来想让女神自己动,关键得用 ...
- Vue源码--解读vue响应式原理
原文链接:https://geniuspeng.github.io/2018/01/05/vue-reactivity/ Vue的官方说明里有深入响应式原理这一节.在此官方也提到过: 当你把一个普通的 ...
- 详解Vue响应式原理
摘要: 搞懂Vue响应式原理! 作者:浪里行舟 原文:深入浅出Vue响应式原理 Fundebug经授权转载,版权归原作者所有. 前言 Vue 最独特的特性之一,是其非侵入性的响应式系统.数据模型仅仅是 ...
- vue响应式原理,去掉优化,只看核心
Vue响应式原理 作为写业务的码农,几乎不必知道原理.但是当你去找工作的时候,可是需要造原子弹的,什么都得知道一些才行.所以找工作之前可以先复习下,只要是关于vue的,必定会问响应式原理. 核心: / ...
- 深入Vue响应式原理
深入Vue.js响应式原理 一.创建一个Vue应用 new Vue({ data() { return { name: 'yjh', }; }, router, store, render: h =& ...
- 浅析Vue响应式原理(三)
Vue响应式原理之defineReactive defineReactive 不论如何,最终响应式数据都要通过defineReactive来实现,实际要借助ES5新增的Object.definePro ...
- 深入解析vue响应式原理
摘要:本文主要通过结合vue官方文档及源码,对vue响应式原理进行深入分析. 1.定义 作为vue最独特的特性,响应式可以说是vue的灵魂了,表面上看就是数据发生变化后,对应的界面会重新渲染,那么响应 ...
- 深度解析 Vue 响应式原理
深度解析 Vue 响应式原理 该文章内容节选自团队的开源项目 InterviewMap.项目目前内容包含了 JS.网络.浏览器相关.性能优化.安全.框架.Git.数据结构.算法等内容,无论是基础还是进 ...
- vue响应式原理解析
# Vue响应式原理解析 首先定义了四个核心的js文件 - 1. observer.js 观察者函数,用来设置data的get和set函数,并且把watcher存放在dep中 - 2. watcher ...
随机推荐
- Arduino库和STM32的寄存器、标准库、HAL库、LL库开发比较之GPIO
标题: Arduino库和STM32的寄存器.标准库.HAL库.LL库开发比较之GPIO 作者: 梦幻之心星 sky-seeker@qq.com 标签: [#Arduino,#STM32,#库,#开发 ...
- external-attacher源码分析(1)-main方法与启动参数分析
更多 ceph-csi 其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 摘要 ceph-csi分析-external-attacher源码分析.external- ...
- Redis 雪崩、穿透、击穿、并发、缓存讲解以及解决方案
1.缓存雪崩 数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机. 比如一个雪崩的简单过程 1.redis集群大面积故障 2.缓存 ...
- ES服务的搭建(八)
看下图的淘宝页面,可以看到搜索有多个条件及搜索产品,并且支持多种排序方式,例如按价格:其实这块有个特点,就是不管你搜索哪个商品他都是有分类的,以及他对应的品牌,这两个是固定的,但其它参数不一定所有商品 ...
- oracle查询用户所在表为空的表名
1 select * from user_tables where num_rows = 0 查询之后发现查询的不全,查询之后发现num_rows为空 select * from user_table ...
- POJ 1556 计算几何 判断线段相交 最短路
题意: 在一个左下角坐标为(0,0),右上角坐标为(10,10)的矩形内,起点为(0,5),终点为(10,5),中间会有许多扇垂直于x轴的门,求从起点到终点在能走的情况下的最短距离. 分析: 既然是求 ...
- Sql Server 查询正在执行的sql信息和锁定事务
执行中的sql SELECT [Spid] = session_Id, ecid, [Database] = DB_NAME(sp.dbid), [User] = nt_username, [Stat ...
- springboot 使用yml配置文件自定义属性
springboot 中在application.yml文件里自定义属性值,配合@Value注解可以在代码中直接取到相应的值,如在application.yml中添加 mqtt: serverURI: ...
- linux学习之路第八天(组管理和权限管理)
组管理和权限管理 1.Linux 组基本介绍 在linux中的每个用户必须属于一个组,不能独立于组外.在linux中每个文件有所有者,所在组,其他组的概念 1)所有者 2)所在组 3)其它组 4)改变 ...
- 《Linux基础知识及命令》系列分享专栏
<Linux基础知识及命令>系列分享专栏 本专题详细为大家讲解了Linux入门基础知识,思路清晰,简单易懂.本专题非常适合刚刚学习Linux的小白来学习,通过学习该专题会让你由入门达到中级 ...