Vue双向绑定原理 从vue2的Object.defineProperty到vue3的proxy
在网上查找资料的时候,看到很多关于Vue双向绑定的文章都直接说是通过Object.defineProperty实现的,但我隐约记得去年看过尤大的视频,记得好像是用proxy实现的,所以又好好找了一下,果然,在vue3.0中,已经改用proxy实现了
双向绑定的简单思路
在谈论vue2和vue3中各自的双向绑定形式前,我们先了解一下基本的思路
要做到双向绑定,即是在我们修改数据时,视图发生变化,而在视图发生变化时,我们要去修改其对应的数据,而视图的变化,相对简单,因为我们可以使用各种监听事件,当事件被触发时,我们就去修改相应的数据,这里可以使用发布-订阅的设计模式来实现。而数据的变化,相对来说就难以去监听了,因为数据没有所谓的事件,所以我们要去采用别的方式
这个方式就是数据劫持,当我们访问或修改对象的属性时,就会触发相应的事件。事实上就是劫持set和get操作,当数据发生变化时触发事件
所以实现双向绑定的基本思路就是发布-订阅+数据劫持
vue2.x
————————————————
在vue2.x中,双向绑定是通过监听对象的get和set操作来实现的,即是Object.defineProperty
我们通过Object.defineProperty的使用来简单地展示一下如何通过监听数据的变化来改变视图
首先明确一下Object.defineProperty的用法,Object.defineProperty用来监听对象的属性,这里监听set和get操作
————————————————
let obj={
a:1
}
let val=1
let newVal=2
Object.defineProperty(obj,'a',{
get(){
console.log('数据被获取')
return val
},
set(){
console.log('数据被修改/设置')
val = newVal
}
})
这样每当我们获取obj的a属性或者设置修改a属性的时候,都会被劫持并打印出相应的内容,而在vue2.x中正是采用这种监听方式
使用发布-订阅模式,data上的数据即是发布方,而视图的修改是订阅方,每当数据发生修改时,就会发布信息,而订阅方接受到相应的信息,就会对视图进行修改,这样就达到了数据修改时改变视图的目的,我们来模仿一下这个发布订阅的过程
let publisher = function() {
return {
currentList: [],
add: function(subscriber) {
this.currentList.push(subscriber)
},
publish: function(key,content) {
let currentList = this.currentList
for (let i = 0; i < currentList.length; i++) { // 遍历订阅者的数组
currentList[i].receiveText(key,content)
}
}
}
}
let subscriber = function(name) {
return {
receiveText: function(key,content) {
console.log(`视图${key}已更新,相应的内容为${content}`)
}
}
}
// 将data作为发布方
let data = publisher()
// 把视图修改作为订阅方
let change = subscriber()
// 让视图修改订阅data的更新
data.add(change)
data._a=1
Object.defineProperty(data,'a',{
get(){
return data._a
},
set(val){
data.publish('a',val)
data._a = val
}
})
这样子,当我们修改data的a属性时,相应的“视图”就会发生改变了
vue3.0
虽然Object.defineProperty可以做到我们想要的双向绑定的效果,但是在proxy出现后,它就被替代掉了
通过上面的操作我们也看到了,Object.defineProperty只能一个属性一个属性地监听,,也就是说,对于data对象,我们需要进行深度遍历,去监听每一个属性的变化,而一旦我们对data一个比较深的对象直接修改它的值,那么就又得对其进行重新地遍历,非常损耗性能
反观proxy,proxy可以监听一整个对象,且基于proxy的监听,只有当一个数据被用到的时候,才会去监听它,所以就避免了上面提及的问题,在监听上大大降低了性能的消耗
proxy
proxy是ES6中出现的新语法,可以劫持对象的13种操作,其中就有set和get的操作
————————————————
let p = new Proxy({a:1}, {
get: function(target, property,receiver) {
console.log('劫持到get操作')
return Reflect.get(target, property, receiver)
},
set:function(target,property,value,receiver){
console.log('劫持到set操作');
return Reflect.set(target, key, value, receiver);
},
})
let obj = Object.create(p)
具体的proxy使用详看ES6学习笔记(十二)Proxy代理
模拟数据监听修改视图
一样的,在vue3.0中,依然是使用发布-订阅方式来实现信息修改的发布,用一段代码来模拟一下
var publisher = function() {
return {
currentList: [],
add: function(subscriber) {
this.currentList.push(subscriber)
},
publish: function(key,content) {
let currentList = this.currentList
for (let i = 0; i < currentList.length; i++) { // 遍历订阅者的数组
currentList[i].receiveText(key,content)
}
}
}
}
var subscriber = function(name) {
return {
receiveText: function(key,content) {
console.log(`视图${key}已更新,相应的内容为${content}`)
}
}
}
// 将data作为发布方
let data = publisher()
// 把视图修改作为订阅方
let change = subscriber()
// 让视图修改订阅data的更新
data.add(change)
let proxy = new Proxy(change,{
set:function(target,prototype,value,receiver){
change.receiveText(prototype,value)
return Reflect.set(target,prototype.value,receiver)
}
})
相比于上面针对一个个属性设置监听,这里我们只需要对这整个对象进行监听,不管我们修改的是哪个属性,都会被劫持
原文链接:https://blog.csdn.net/zemprogram/article/details/103404763
Vue双向绑定原理 从vue2的Object.defineProperty到vue3的proxy的更多相关文章
- [Vue源码]一起来学Vue双向绑定原理-数据劫持和发布订阅
有一段时间没有更新技术博文了,因为这段时间埋下头来看Vue源码了.本文我们一起通过学习双向绑定原理来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫 ...
- Vue双向绑定原理,教你一步一步实现双向绑定
当今前端天下以 Angular.React.vue 三足鼎立的局面,你不选择一个阵营基本上无法立足于前端,甚至是两个或者三个阵营都要选择,大势所趋. 所以我们要时刻保持好奇心,拥抱变化,只有在不断的变 ...
- vue双向绑定原理分析
当我们学习angular或者vue的时候,其双向绑定为我们开发带来了诸多便捷,今天我们就来分析一下vue双向绑定的原理. 简易vue源码地址:https://github.com/jiangzhenf ...
- vue双向绑定原理及实现
vue双向绑定原理及实现 一.总结 一句话总结:vue中的双向绑定主要是通过发布者-订阅者模式来实现的 发布 订阅 1.单向绑定和双向绑定的区别是什么? model view 更新 单向绑定:mode ...
- Vue双向绑定原理(源码解析)---getter setter
Vue双向绑定原理 大部分都知道Vue是采用的是对象的get 和set方法来实现数据的双向绑定的过程,本章将讨论他是怎么利用他实现的. vue双向绑定其实是采用的观察者模式,get和s ...
- vue 学习二 深入vue双向绑定原理
vue双向绑定原理 请示总体来讲 就是为data的中的每个属性字段添加一个getter/seter属性 以此来追踪数据的变化,而执行这部操作,依赖的就是js的Object.defineProperty ...
- Vue双向绑定原理梳理
简介 vue数据双向绑定主要是指:数据变化更新视图,视图变化更新数据. 实现方式:数据劫持 结合 发布者-订阅者 模式. 数据劫持通过 Object.defineProperty()方法. 对对象的劫 ...
- vue双向绑定原理
要了解vue的双向绑定原理,首先得了解Object.defineProperty()方法,因为访问器属性是对象中的一种特殊属性,它不能直接在对象中设置,而必须通过 Object.definePrope ...
- 通俗易懂了解Vue双向绑定原理及实现
看到一篇文章,觉得写得挺好的,拿过来给大家分享一下,刚好解答了一些困扰我的一些疑惑!!! 1. 前言 每当被问到Vue数据双向绑定原理的时候,大家可能都会脱口而出:Vue内部通过Object.defi ...
- Vue双向绑定原理及其实现
在之前面试的时候被面试官问到是否了解Vue双向绑定的原理,其实自己之前看过双向绑定的原理,但也就是粗略的了解,但是没有深入.面试官当时让我手写一个原理,但是就蒙了
随机推荐
- NodeJS增删改查的获取方法
get獲取方法 ctx.query post獲取方法 ctx.request.body delete ctx.request.body put ctx.query ctx.request.body
- Python异步爬取梁羽生小说网
才知道写在文章里面不是原创... https://www.cnblogs.com/kebei/articles/14659937.html
- PyQt5模块说明
pyqt5的类别分为几个模块,包括以下: QtCoreQtGuiQtWidgetsQtMultimediaQtBluetoothQtNetworkQtPositioningEnginioQtWebSo ...
- vue学习之-----组件递归调用
1.关键点 2.父组件 <template> <div> <div class="btn-title"> <el-button @clic ...
- kubernetes:v1.25 + containerd
由于kubernets从v1.24开始停止支持dockershim,kubernets不再支持通过docker来创建和管理容器.本文记录安装kubernetes v1.25 + containerd ...
- [js函数] shallowEqual
const isBasicType = (t: any) => { return t === "number" || t === "string" || ...
- OV5640数据的解码
为了配合开发板的使用,笔者搞了一个OV5640的摄像头模组,OV5640具体的相关手册及资料网上已经很多,感兴趣的都可以自行去查找,基本大同小异.这里也不把OV5640初始化的代码贴出来,因为就是简单 ...
- ESXi 基础安全加强(ing...)
# 查看防火墙规则esxcli network firewall ruleset allowedip list # 允许指定ip使用web服务和客户端访问[root@localhost:~] esxc ...
- 2.9 系统IO
iostream: 输入流 cin; c 指代 character 输出流 cout, cerr(立即刷新缓冲区), clog(缓冲区满后刷新) 命名空间 访问方式 namespace NameSpa ...
- MySQL Delete 表数据后,磁盘空间并未释放,为什么?
有开发小哥咨询了一个问题,记录一下处理过程分享给有需要的朋友.问题如下:MySQL数据库中有几张表增删比较频繁.数据变动剧烈且数据量大,导致数据增长过快,磁盘占用多.为了节约成本,定期进行数据备份,并 ...