😁 作者简介:一名大四的学生,致力学习前端开发技术
⭐️个人主页:夜宵饽饽的主页
❔ 系列专栏:Vue小贴士
👐学习格言:成功不是终点,失败也并非末日,最重要的是继续前进的勇气
🔥前言:
这里是我整理的关于Vue中双向绑定和响应式原理的理解,还有关于Vue3和Vue2版本响应式的区别,希望可以帮助到大家,欢迎大家的补充和纠正
vue 响应式原理以及双向绑定实现代码 ?
一、 双向绑定
双向绑定可以理解成:
第一向:数据驱动视图,通过getter/setter提前设置数据改变之后的回调来完成
第二向:视图到数据,通过事件驱动,通常涉及的是用户交互
双向绑定的核心就是响应式系统
二、响应式原理:
1)数据劫持
Vue使用名为Observer的类来实现数据劫持,当创建Vue实例时,Vue会遍历传入的数据对象,对其进行遍历递归并使用Object.defineProperty方法将对象的属性转化为"响应式"属性
2)建立依赖追踪关系
在属性转化为响应式属性时,Vue会为每一个属性创建Dep依赖对象,用于收集当前属性的依赖关系
3)依赖收集
当访问一个响应式数据时,Vue会在访问的过程中收集依赖,这是通过在getter方法中进行依赖追踪来实现的,在getter方法中,Vue会判断是否存在Dep对象,如果存在将Dep对象添加到依赖列表中,这样就建立了依赖关系,将属性和对应的Watcher对象关联起来
4)响应更新
当属性发生变化时,Vue会触发属性的setter方法,并通知该属性的Dep对象,然后Dep对象会遍历依赖列表,通知每一个依赖的Watcher对象进行更新操作
这就是响应式原理,也被称为发布订阅
🌱vue2中简单实现的响应式系统
javascript
/**
* 订阅-发布,get订阅,set发布
*/
class Dep{
constructor(){
this.subscribers=new Set()
}
depend(){
//判断依赖目标。空时没有意义的
if(Dep.target){
this.subscribers.add(Dep.target)
}
}
notify(){
this.subscribers.forEach(el=>el())
}
}
Dep.target=null
function defineReactive(obj,key,val){
const dep=new Dep()
Object.defineProperty(obj,key,{
enumerable:true,
configurable:true,
get:function reactiveGetter (){
dep.depend()
return val
},
set:function reactiveSetter (newVal){
if(newVal===val) return
val=newVal
dep.notify()
}
})
}
function watcher(fun){
Dep.target=fun
fun()
Dep.target=null
}
let data={age:15,number:3}
defineReactive(data,'age',data.age)
defineReactive(data,'number',data.number)
let total=0
watcher(()=>{
total=data.age * data.number
})
console.log(total)
data.age=20
console.log(total)
🌱vue3中简单实现的响应式系统
javascript
class Dep{
constructor(){
this.subscribers=new Set()
}
depend(){
if(Dep.target){
this.subscribers.add(Dep.target)
}
}
notify(){
this.subscribers.forEach(el=>el())
}
}
function definereactive(target){
const dep=new Dep()
let handle={
get(target,key,receiver){
dep.depend()
return Reflect.get(target,key,receiver)
},
set(target,key,value,receiver){
if(target[key]===value) return true
Reflect.set(target,key,value,receiver)
dep.notify()
}
}
return new Proxy(target,handle)
}
Dep.target=null
function watcher(fun){
Dep.target=fun
fun()
Dep.target=null
}
let data={age:15,number:2}
let proxyData=definereactive(data)
let total=0
watcher(()=>{
total=proxyData.age * proxyData.number
})
console.log(total)
proxyData.number=4
console.log(total)
总结
⭐Vue3中改用proxy的利弊
放弃了对低版本浏览器的兼容,换来了三点的提升
- 对属性的添加和删除动作的监测
- 对数组基于下标的修改的监测
- 对Map,Set,WeakMap,WeakSet的支持