目录
分析一下reactive
Vue2的Object.defineProperty
Vue3的Proxy
ref
首页 web前端 Vue.js 一文详解Vue中响应式原理

一文详解Vue中响应式原理

Feb 13, 2023 pm 07:30 PM
前端 设计模式 vue.js

本篇文章带大家学习Vue,深入了解Vue中响应式原理,希望对大家有所帮助!

一文详解Vue中响应式原理

以此文纪念将要逝去的响应式语法糖

废话不多说,直接进入正题,响应式在日常开发中的应用是很常见的,这里举个简单的例子:

let a=3
let b=a*10
console.log(b)//30
a=4
console.log(b)//40
登录后复制

这时候我们想让b=4*10,这样显然是不行的,即使我们在前面加上个var也只会发生变量提升,我们所给的值并不会提升。

而这个时候,响应式的作用就体现出来了:

import { reactive } from 'vue'

let state = reactive({ a: 3 })
let b = computed(() => state.a * 10)
console.log(b.value) // 30
state.a = 4
console.log(b.value) // 40
登录后复制

只需要一个简单的响应式API便可实现跟踪变化的效果。【相关推荐:vuejs视频教程web前端开发

分析一下reactive

事实上,Vue3的reactive的本质上就是一个发布订阅模式

通过创建依赖图来跟踪数据的依赖关系。依赖图是一个图形,它描述了哪些数据是依赖于哪些数据的。当数据发生变化时,Vue 3 的 reactive 系统会自动触发视图的更新。这是因为它在依赖图中跟踪了数据变化,并通过将其与视图的更新关联起来来实现的

这里我列出尤大在Vue Master里演示的代码做个简单的示例:

class Dep{
    constructor(value){
        this.subscribers=new Set()
        this._value=value
    }
    get value(){
        this.depend()
        return this._value
    }
    set value(newValue){
        this._value=newValue
        this.notify()
    }
    depend(){
        if(activeEffect){
            this.subscribers.add(activeEffect)
        }
    }
    notify(){
        this.subscribers.forEach(effect=>{
            effect()
        })
    }
}
登录后复制

我们来分析一下这段代码:

  • 定义一个subscribe属性,作为一个订阅者列表,用来存储所有的订阅者信息
  • depend函数用来管理依赖关系,即该订阅者所依赖的该变量
  • notify函数便是作为通知所有订阅者该变量的值已经发生变化

当变量的值发生变化的时候,它便可以自动的通知所有的订阅者进行更新了

Vue2的Object.defineProperty

事实上,在Vue2时期,响应式的都是交给Object.defineProperty来实现的,但在Vue3当中切换成了Proxy,我们等下来结合实际代码来看原因;我们先来看看Vue2是如何实现的:

function reactive(raw){
    Object.keys(raw).forEach(ket=>{
        const dep=new Dep()
        let value=raw[key]
        
        Object.definProperty(raw,key,{
            get(){
                dep.depend()
                return value
            },
            //当属性发生
            set(newValue){
                value=newValue
                dep.notify()
            }
        })
    })
    //这时候返回的原始对象已经具有响应性
    return raw
}
登录后复制

这样一个简单的响应式API就实现了

但这里缺点也就很明显了:在 Vue 2.x 中,被传入的对象会直接被 Vue.observable 变更 而在Vue3当中,则是会返回一个可响应的代理,而对源对象直接进行变更仍然是不可响应的

这就导致了:

  • 当我们添加或者删除对象的属性时,Vue2的响应式是无法检测的,由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的
  • 无法检测数组下标和长度的变化

当然,这个属于历史局限了,当时ES5也就只能选择Object.definProperty,但在了ES6版本,便多了Proxy,这时候Vue的响应式便得到了升级

Vue3的Proxy

Vue3采用Proxy来监控数据的变化,相较于Vue2来说,不仅解决了上述的问题,还有这些优势:

  • 无需再使用vue.$set来触发响应式,这让代码看上去能过更加简介
  • 全方位的数组变化检测,消除Vue2中无效边界情况
  • 减少了Vue3中书写响应式的代码量,这让我们的开发更加方便

让我们来看看实际代码是什么样子的:

const reactiveHandles={
    get(target,key,receiver){
        const dep=getDep(target,key)
        dep.depend()
        return Reflect.get(target,key,receiver)
    },
    set(target,key,value,receiver){
        const dep=getDep(target,key)
        const result=Reflect.set(target,key,value,receiver)
        dep.notify()
        return result
    }
}
登录后复制

通过对对象进行收集依赖来实现响应式的方式也便是Vue3响应式的精髓

ref

在官方文档有句话:reactive() 的种种限制归根结底是因为 JavaScript 没有可以作用于所有值类型的 “引用” 机制,而reactive的限制便是:

  • 只能处理可被观测的数据结构,如数组和对象;而不可观测的数据结构,如原始数据类型就无法被其监测
  • 只能处理定义在它所在组件的数据,不能处理全局变量

而这个时候就需要ref来登场了,ref便是针对基本数据类型而诞生的,弥补了reactive的缺陷,简单的来说,ref更加适合简单的单个可变值(不过实际开发大多数时候都是ref一把梭哈哈哈

这里顺便提一下,响应式语法糖的提案被取消了还是蛮可惜的

(学习视频分享:vuejs入门教程编程基础视频

以上是一文详解Vue中响应式原理的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Java框架中设计模式与架构模式的区别 Java框架中设计模式与架构模式的区别 Jun 02, 2024 pm 12:59 PM

在Java框架中,设计模式和架构模式的区别在于:设计模式定义了在软件设计中解决常见问题的抽象解决方案,关注类和对象之间的交互,如工厂模式。架构模式定义了系统结构和模块之间的关系,关注系统组件的组织和交互,如分层架构。

vue.js vs.反应:特定于项目的考虑因素 vue.js vs.反应:特定于项目的考虑因素 Apr 09, 2025 am 12:01 AM

Vue.js适合中小型项目和快速迭代,React适用于大型复杂应用。1)Vue.js易于上手,适用于团队经验不足或项目规模较小的情况。2)React的生态系统更丰富,适合有高性能需求和复杂功能需求的项目。

Vue.js很难学习吗? Vue.js很难学习吗? Apr 04, 2025 am 12:02 AM

Vue.js不难学,特别是对于有JavaScript基础的开发者。1)其渐进式设计和响应式系统简化了开发过程。2)组件化开发让代码管理更高效。3)使用示例展示了基本和高级用法。4)常见错误可以通过VueDevtools调试。5)性能优化和最佳实践如使用v-if/v-show和key属性可提升应用效率。

VUE是用于前端还是后端? VUE是用于前端还是后端? Apr 03, 2025 am 12:07 AM

Vue.js主要用于前端开发。1)它是一个轻量级且灵活的JavaScript框架,专注于构建用户界面和单页面应用。2)Vue.js的核心是其响应式数据系统,数据变化时视图自动更新。3)它支持组件化开发,UI可拆分为独立、可复用的组件。

Java设计模式之装饰器模式剖析 Java设计模式之装饰器模式剖析 May 09, 2024 pm 03:12 PM

装饰器模式是一种结构型设计模式,允许动态添加对象功能,无需修改原始类。它通过抽象组件、具体组件、抽象装饰器和具体装饰器的协作实现,可以灵活扩展类功能,满足变化的需求。示例中,将牛奶和摩卡装饰器添加到Espresso,总价为2.29美元,展示了装饰器模式在动态修改对象行为方面的强大功能。

PHP设计模式:测试驱动开发实践 PHP设计模式:测试驱动开发实践 Jun 03, 2024 pm 02:14 PM

TDD用于编写高质量PHP代码,步骤包括:编写测试用例,描述预期功能并使其失败。编写代码,仅使测试用例通过,无需过分优化或详细设计。测试用例通过后,优化和重构代码以提高可读性、可维护性和可扩展性。

Guice框架中设计模式的应用 Guice框架中设计模式的应用 Jun 02, 2024 pm 10:49 PM

Guice框架应用了多项设计模式,包括:单例模式:通过@Singleton注解确保类只有一个实例。工厂方法模式:通过@Provides注解创建工厂方法,在依赖注入时获取对象实例。策略模式:将算法封装成不同策略类,通过@Named注解指定具体策略。

java框架中使用设计模式的优缺点有哪些? java框架中使用设计模式的优缺点有哪些? Jun 01, 2024 pm 02:13 PM

Java框架中使用设计模式的优点包括:代码可读性、可维护性和可扩展性增强。缺点包括:过度使用导致复杂性、性能开销以及学习曲线陡峭。实战案例:代理模式用于延迟加载对象。明智地使用设计模式可充分利用其优势并最小化缺点。

See all articles