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 中,我们通常将静态资源放在 public 目录下,这些静态资源可以是样式表、脚本、图片、字体等文件。在访问这些静态资源时,我们可以给它们增加路由前缀,以便更好地管理和部署我们的应用程序。 一种实现方式是通过修改 vue.config.js 文件,该文件是 Vue CLI 3.x 新增的配置文件,用于存放项目构建配置。我们可以在 publicPat…

    Vue 2023年5月28日
    00
  • Vue面试必备之防抖和节流的使用

    当谈论Vue的面试必备技能时,防抖和节流的使用肯定是少不了的。在Vue开发中,我们经常需要对用户的输入进行 debounce(防抖) 或 throttle(节流) 的处理,以避免过度触发重压服务器,影响用户体验。那么,接下来我将详细讲解防抖和节流的使用以及如何在Vue中灵活运用这两个技术。 一、什么是防抖和节流? 1. 防抖 防抖是指在事件被触发n秒后再执行…

    Vue 2023年5月27日
    00
  • vuex进阶知识点巩固

    关于 “vuex进阶知识点巩固” 的完整攻略,我将按照以下几个方面进行详细讲解: Vuex的基本概念 Vuex的核心概念 Vuex的高级应用 1. Vuex的基本概念 1.1 什么是Vuex? Vuex是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,将组件的共享状态抽取出来,以一个全局单例模式管理。 1.2 V…

    Vue 2023年5月28日
    00
  • vue常用指令代码实例总结

    Vue常用指令代码实例总结攻略 什么是Vue指令 Vue指令是一种特殊的HTML属性, 它们以v-前缀开头,用于渲染模板。指令中可以包含绑定表达式,该表达式的值被动态计算,并且可以自动响应数据变化。 Vue指令有很多种,下面我们来详细讲解一些常用指令的代码实例。 v-if指令 v-if 指令用于根据表达式的值来有条件地渲染某个元素,如果表达式的值为false…

    Vue 2023年5月27日
    00
  • mpvue+vuex搭建小程序详细教程(完整步骤)

    这里给您详细讲解一下“mpvue+vuex搭建小程序详细教程(完整步骤)”。 简介 本教程将介绍如何使用 mpvue 和 vuex 搭建一个小程序。mpvue 是一个使用 Vue.js 开发小程序的前端框架,而 vuex 则是 Vue.js 的状态管理工具。本次教程的重点是如何使用 vuex 在 mpvue 中控制状态的管理。 步骤 1. 创建一个 mpvu…

    Vue 2023年5月27日
    00
  • Vue实现输入框回车发送和粘贴文本与图片功能

    下面是Vue实现输入框回车发送和粘贴文本与图片功能的完整攻略。 步骤一:引入依赖 在Vue项目中引入vue-clipboard2和vue-filepond这两个库。 npm install vue-clipboard2 vue-filepond 步骤二:注册组件和事件 <template> <div> <input type=&…

    Vue 2023年5月27日
    00
  • vue的for循环使用方法

    下面是关于Vue的for循环使用方法的详细攻略。 一、Vue的for循环介绍 Vue中的for循环指令叫做v-for,它可以遍历一个数组或一个对象并为每个成员渲染出对应的元素。采用v-for指令可以用于对每个数组和对象进行迭代,并将每个元素渲染到页面中。在渲染每个元素时,我们可以对它们分别进行修改和操作,实现前端页面的数据动态呈现效果。 二、Vue的for循…

    Vue 2023年5月28日
    00
  • 基于java实现websocket协议过程详解

    基于Java实现WebSocket协议过程详解 什么是WebSocket WebSocket是HTML5规范中的协议,它允许在客户端和服务器之间建立一种双向通信的协议,即WebSocket连接。该连接是基于TCP的,它通过在HTTP/1.1之上进行协商升级,可以在客户端和服务器之间创建持久性的连接,实现低延迟、高效率的实时通信。 WebSocket连接的建立…

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