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

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自动构建发布脚本的方法示例”的完整攻略。 1. 确定需求 在实现自动构建发布脚本之前,我们需要先确定具体的需求,以便确定脚本的功能和实现方案。一般来说,自动构建发布脚本的主要功能包括: 构建前的准备工作,如环境依赖检查、代码检查等; 代码的自动构建和打包; 代码的自动部署和发布。 2. 创建脚本 第二步是开始创建脚本。Vue自动构建…

    Vue 2023年5月27日
    00
  • vue封装一个简单的div框选时间的组件的方法

    下面是详细讲解“vue封装一个简单的div框选时间的组件的方法”的完整攻略和示范代码。 1. 设计组件的props和data 首先,我们需要考虑这个div框选时间的组件需要哪些props和data。 开始时间和结束时间的默认值 可选的开始时间和结束时间范围,一般情况下为当前时间到未来若干天 组件的宽度和高度 根据上述内容,我们可以设计出如下的props和da…

    Vue 2023年5月29日
    00
  • vue.js中$set与数组更新方法

    当使用 Vue.js 进行开发的时候,因其响应式的数据绑定特性,我们通常使用数组来绑定和更新数据。但是由于 JavaScript 的限制,Vue.js 并不能检测数组的变化,比如直接改变数组的某个元素,或者修改数组的长度,这样就会导致视图不会更新而产生问题。因此,我们需要使用一些特殊的方法来更改数组并确保视图更新,Vue.js 提供了两种方法: 直接利用 V…

    Vue 2023年5月28日
    00
  • uniapp和vue的区别详解

    一、什么是uniapp和vue? Uniapp是一个基于Vue框架开发的、可同时发布到多个平台的前端框架。它由DCloud团队开发,并已获得多个开发者的认可和支持。Uniapp可发布到微信小程序、App、H5等多个平台,具备一定的跨平台能力。 Vue.js是一个渐进式JavaScript框架,以响应式和MVVM模式为核心,通过简洁的语法和丰富的组件系统,帮助…

    Vue 2023年5月27日
    00
  • vue 使用lodash实现对象数组深拷贝操作

    将 Vue 中的对象和数组进行深拷贝操作通常需要使用第三方库来进行操作。Lodash 是一个支持多种操作的 JavaScript 实用工具库,其中就包含了深拷贝操作。下面就是关于在 Vue 中使用 Lodash 实现对象数组深拷贝的详细攻略。 步骤一:安装 Lodash 从 Lodash 的官网上可以下载到 Lodash 的压缩包,也可以直接使用 npm 进…

    Vue 2023年5月29日
    00
  • SpringBoot实现滑块验证码验证登陆校验功能详解

    下面我将为你详细讲解“SpringBoot实现滑块验证码验证登陆校验功能”的完整攻略。 1. 概述 在本文中,我们将介绍使用SpringBoot来实现滑块验证码验证登陆校验功能的完整攻略。其中,我们使用了阿里云的滑块验证码服务和Spring Security框架来完成。 本文将分为以下几个部分: 阿里云滑块验证码服务介绍 SpringBoot集成阿里云滑块验…

    Vue 2023年5月28日
    00
  • Vue请求JSON Server服务器数据的实现方法

    当你使用Vue来开发Web应用时,你需要获取外部数据并在网页应用中展示这些数据。JSON Server是一个快速的、简单的node.js库,可以模拟RESTful APIs,生成假数据,并对数据进行增删改查操作。下面是在Vue中如何实现JSON Server服务器数据请求。 1. 安装JSON Server 首先,你需要安装JSON Server。在命令行中…

    Vue 2023年5月28日
    00
  • vue项目实现文件下载进度条功能

    下面是“vue项目实现文件下载进度条功能”的完整攻略: 服务端实现文件下载接口 首先,在服务器端需要实现一个文件下载的接口,将需要下载的文件流返回给客户端。根据不同的后端语言和框架,具体实现会有所差异。这里以 Node.js 和 Express 框架为例,示例如下: // 下载文件接口 app.get(‘/download’, (req, res) =&gt…

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