【Vue】Vue中响应式原理和双向绑定的实现

😁 作者简介:一名大四的学生,致力学习前端开发技术

⭐️个人主页:夜宵饽饽的主页

❔ 系列专栏: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的利弊

放弃了对低版本浏览器的兼容,换来了三点的提升

  1. 对属性的添加和删除动作的监测
  2. 对数组基于下标的修改的监测
  3. 对Map,Set,WeakMap,WeakSet的支持
相关推荐
June_liu19 分钟前
列太多vxe-table自动启用横向虚拟滚动引起的bug
前端·javascript
云枫晖28 分钟前
手写Promise-then的基础实现
前端·javascript
养生达人_zzzz28 分钟前
飞书三方登录功能实现与行业思考
前端·javascript·架构
GarrettGao30 分钟前
Frida常见用法
javascript·python·逆向
肥晨1 小时前
前端私有化变量还只会加前缀嘛?保姆级教程教你4种私有化变量方法
前端·javascript
小高0071 小时前
前端 Class 不是花架子!3 个大厂常用场景,告诉你它有多实用
前端·javascript·面试
没有鸡汤吃不下饭2 小时前
前端【数据类型】 No.1 Javascript的数据类型与区别
前端·javascript·面试
码流之上2 小时前
【一看就会一写就废 指间算法】设计电子表格 —— 哈希表、字符串处理
javascript·算法
Asort5 小时前
JavaScript 从零开始(七):函数编程入门——从定义到可重用代码的完整指南
前端·javascript
真夜5 小时前
关于rngh手势与Slider组件手势与事件冲突解决问题记录
android·javascript·app