【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的支持
相关推荐
zongzi_4941 小时前
二次封装的天气时间日历选择组件
开发语言·javascript·ecmascript
麻辣_水煮鱼1 小时前
vue数据变化但页面不变
前端·javascript·vue.js
一条晒干的咸魚1 小时前
【Web前端】实现基于 Promise 的 API:alarm API
开发语言·前端·javascript·api·promise
WilliamLuo2 小时前
MP4结构初识-第一篇
前端·javascript·音视频开发
过期的H2O22 小时前
【H2O2|全栈】JS进阶知识(七)ES6(3)
开发语言·javascript·es6
前端Hardy2 小时前
HTML&CSS:数据卡片可以这样设计
前端·javascript·css·3d·html
松树戈2 小时前
JS推荐实践
开发语言·javascript·ecmascript
vener_3 小时前
LuckySheet协同编辑后端示例(Django+Channel,Websocket通信)
javascript·后端·python·websocket·django·luckysheet
老码沉思录3 小时前
React Native 全栈开发实战班 - 性能与调试之打包与发布
javascript·react native·react.js
计算机毕设孵化场3 小时前
计算机毕设-基于springboot的多彩吉安红色旅游网站的设计与实现(附源码+lw+ppt+开题报告)
vue.js·spring boot·后端·计算机外设·课程设计·计算机毕设论文·多彩吉安红色旅游网站