Vue响应式原理Observer、Dep、Watcher理解

yizhihongxing

Vue是一个响应式框架,其核心就是实现数据的双向绑定,而Vue双向绑定的实现就是基于其响应式原理的。Vue响应式原理由Observer、Dep、Watcher三个核心模块组成。本文将详细讲解Vue响应式原理的三个核心模块,以及通过两个示例来说明Vue响应式原理的使用。

一、Observer

Vue的Observer模块负责监听数据的变化,从而通知相应的监听器进行更新。Vue的Observer使用了ES5的Object.defineProperty方法来实现,在对属性进行读写操作时,Observer通过getter和setter劫持了数据的读写操作,并在该属性发生变化时,通知其相应的Watcher进行更新。

下面是一个简单的示例说明Vue的Observer模块的使用:

const data = {msg: 'Hello, Vue!'}

function observe(data) {
    if (!data || typeof data !== 'object') {
        return
    }

    Object.keys(data).forEach((key) => {
        defineReactive(data, key, data[key])
    })
}

function defineReactive(data, key, value) {
    let dep = new Dep() // 创建依赖实例

    Object.defineProperty(data, key, {
        enumerable: true,
        configurable: true,
        get() {
            if (Dep.target) {
                dep.addSub(Dep.target) // 添加监听器
            }

            return value
        },
        set(newValue) {
            if (newValue === value) {
                return
            }

            value = newValue
            dep.notify() // 通知监听器更新
        }
    })
}

class Dep {
    constructor() {
        this.subs = [] // 监听器列表
    }

    addSub(sub) {
        if (sub && sub.update) {
            this.subs.push(sub) // 添加监听器
        }
    }

    notify() {
        this.subs.forEach(sub => {
            sub.update() // 通知监听器更新
        })
    }
}

observe(data) // 监听数据变化

data.msg = 'Hello, Vue!' // 触发数据更新

在该示例中,我们定义了一个包含msg属性的对象data,并使用observe函数对其进行数据的监听。在defineRective函数中,我们创建一个Dep实例,存放当前属性的所有监听器,在数据发生变化时,调用Dep实例的notify方法,通知其所有监听器执行update函数进行更新。其中,我们使用了Object.defineProperty方法对属性进行读写操作的劫持,将Observer注入到了属性的getter和setter中。

二、Watcher

Vue的Watcher模块负责收集数据变化的依赖,从而在数据变化时通知视图进行更新。每个Watcher实例会被绑定到一个数据对象的属性上,并在该属性发生变化时执行相应的回调函数。通过Watcher依赖收集,Vue实现了响应式数据和视图之间的双向绑定。

下面是一个简单的示例说明Vue的Watcher模块的使用:

class Watcher {
    constructor(vm, expOrFn, cb) {
        this.vm = vm
        this.cb = cb
        this.expOrFn = expOrFn

        this.value = this.get() // 保存当前值
    }

    get() {
        Dep.target = this // 将当前Watcher实例暴露给依赖收集器,进行依赖收集

        let value = this.vm._data[this.expOrFn] // 获取当前值

        Dep.target = null // 收集完依赖之后,将Watcher实例重置为null,避免重复添加依赖

        return value
    }

    update() {
        let oldValue = this.value
        let newValue = this.vm._data[this.expOrFn]

        if (oldValue !== newValue) {
            this.value = newValue
            this.cb.call(this.vm, oldValue, newValue)
        }
    }
}

observe(data) // 监听数据变化

new Watcher(vm, 'msg', function(oldValue, newValue) {
    console.log(`oldValue: ${oldValue}, newValue: ${newValue}`)
})

data.msg = 'Hello, Vue!' // 触发更新

在该示例中,我们定义了一个Watcher实例,并在其构造函数初始化时,调用get方法获取当前值。在get方法中,我们将当前Watcher实例暴露给依赖收集器,进行依赖收集,并返回当前值。在update方法中,我们通过比较新旧值的差异,判断是否需要执行回调函数,并将回调函数执行。每次数据发生变化,Watcher实例都会重新执行get方法,从而保证视图的实时更新。

三、总结

Vue响应式原理是Vue实现数据双向绑定的核心。Observer模块监听数据的变化,从而在数据发生变化时通知相应的监听器进行视图的更新;Watcher模块收集数据变化的依赖,从而在数据发生变化时通知视图进行更新。通过Observer和Watcher的协作,实现了Vue响应式数据和视图之间的双向绑定。

本文通过两个示例分别说明了Vue响应式原理的Observer、Dep、Watcher理解,在实际开发中,Vue响应式原理的理解对于Vue的使用和调试非常重要,对于同学们深入学习Vue源码和实现原理也有很大帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue响应式原理Observer、Dep、Watcher理解 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • Vue过滤器使用方法详解

    Vue过滤器使用方法详解 Vue是一款流行的前端框架,它提供了过滤器(Filter)功能,可以用于对模板中显示的数据格式进行处理,从而使模板更加易读易懂。本文将详细介绍Vue过滤器的使用方法。 创建过滤器 Vue的过滤器是通过Vue.filter方法来创建的。该方法的第一个参数是过滤器的名称,第二个参数是一个函数。函数接受一个参数,即需要应用过滤器的值,并将…

    Vue 2023年5月27日
    00
  • 详解vue3沙箱机制

    详解Vue3沙箱机制 什么是沙箱机制 沙箱机制是指为了保障安全而采用的一种技术手段,它将组件在运行期间的上下文进行隔离,防止不同组件之间相互影响。Vue3引入了沙箱机制,使得组件的隔离更加彻底,同时也保证了组件的执行效率。 在Vue3中,每个组件都是在自己的沙箱中运行的,每个沙箱都有自己的全局变量、组件注册表、事件系统等。这意味着,在一个组件中定义的变量、组…

    Vue 2023年5月27日
    00
  • Vue echarts模拟后端数据流程详解

    下面是详细讲解 “Vue echarts模拟后端数据流程详解”的完整攻略,包含以下步骤: 1. 安装相关依赖 要使用Vue和echarts,首先需要安装Vue和echarts的相关依赖。使用npm安装如下: npm install –save vue npm install –save echarts 2. 在Vue中引入echarts 为了在Vue中使…

    Vue 2023年5月28日
    00
  • 如何解决ElementPlus的el-table底白线问题

    解决Element Plus的el-table底白线问题可以通过修改CSS样式来完成。步骤如下: 第一步:查看el-table的底部样式 通过浏览器的开发者工具,可以查看到el-table的底部样式,它的CSS类名是.el-table__body-wrapper::after。默认情况下,该样式设置了一个底部白线,并且高度为1像素,颜色为#e4e7ed。 第…

    Vue 2023年5月28日
    00
  • until封装watch常用逻辑简化代码写法

    我来详细讲解一下“until封装watch常用逻辑简化代码写法”的攻略。 什么是until until是Vue.js中一个常用的指令修饰符,它用于监听数据变化直到满足条件才执行操作。常用语法如下: <!– 监听value值变化,直到其等于一个值为9的时候才执行alert方法 –> <div v-on:click="alert(…

    Vue 2023年5月27日
    00
  • vue项目中的支付功能实现(微信支付和支付宝支付)

    下面是关于Vue项目中实现微信支付和支付宝支付的完整攻略。 简介 在Vue项目中需要实现支付功能,常见的方式有微信支付和支付宝支付。微信支付目前还需要申请微信支付商户号,而支付宝支付可以使用支付宝开放平台提供的接口实现。 在项目中可以将支付功能实现为一个组件,以便在需要支付的地方引入使用。 微信支付 微信支付需要完成以下步骤: 申请微信支付商户号; 在项目中…

    Vue 2023年5月27日
    00
  • Vue.js实现立体计算器

    Vue.js实现立体计算器攻略 本文将详细介绍使用Vue.js实现立体计算器的步骤。我们的目标是通过Vue.js搭建一个可交互的立体计算器,支持用户输入高度、宽度、深度等参数,计算并呈现长方体、正方体和球体的体积、表面积等信息。本攻略将包括以下步骤: 搭建基础的Vue.js环境 设计计算器UI界面 实现计算器的基本逻辑 添加计算公式 总结 1. 搭建基础的V…

    Vue 2023年5月28日
    00
  • vue时间组件DatePicker组件的手写示例

    下面是关于“vue时间组件DatePicker组件的手写示例”的完整攻略。 1. 了解DatePicker组件 DatePicker组件是一个常用的时间选择组件。通过DatePicker组件,用户可以自定义时间选择的方式,包括选择年月日、时分秒等。 2. 建立DatePicker组件的基础HTML结构 在进行组件的编写之前,我们需要先建立一个基础HTML结构…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部