Vue之Dep和Observer的用法及说明

yizhihongxing

Vue之Dep和Observer的用法及说明

什么是Dep

Dep(Dependence)是 Vue.js 内部实现响应式的核心。

Dep负责维护和管理所有的Watcher对象,所有被观察者(即响应式数据)的get函数中都会收集自己的依赖(Dep对象)到自己的dep中。

Dep的实现

Dep类的定义如下:

class Dep {
    constructor () {
        this.subs = []
    }

    addSub (sub) {
        this.subs.push(sub)
    }

    removeSub (sub) {
        remove(this.subs, sub)
    }

    depend () {
        if (window.target) {
            window.target.addDep(this)
        }
    }

    notify () {
        // stabilize the subscriber list first
        const subs = this.subs.slice()
        for (let i = 0, l = subs.length; i < l; i++) {
            subs[i].update()
        }
    }
}

Observer 的实现

Observer 将一个对象上的所有属性转化为 getter/setter 的形式,以便“响应式”系统可以侦测到属性的读取和修改事件。当一个响应式数据被访问时(即执行get方法时),Dep会自动把当前的Watcher对象添加到自己的subs数组中,等到数据发生变更时,所有被观察者会被通知更新数据(即执行update方法)。

class Observer {
    constructor (value) {
        this.value = value
        this.dep = new Dep()

        // 重写所有属性的getter/setter
        Object.keys(value).forEach(key => {
            defineReactive(value, key)
        })
    }
}

// 将对象的属性转化为getter/setter的形式
export function defineReactive (obj, key, val) {
    const dep = new Dep()

    const property = Object.getOwnPropertyDescriptor(obj, key)
    if (property && property.configurable === false) {
        return
    }
    const getter = property && property.get
    const setter = property && property.set

    if ((!getter || setter) && arguments.length === 2) {
        val = obj[key]
    }

    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: function reactiveGetter () {
            const value = getter ? getter.call(obj) : val
            if (window.target) {
                dep.depend()
            }
            return value
        },
        set: function reactiveSetter (newVal) {
            const value = getter ? getter.call(obj) : val
            if (newVal === value) {
                return
            }
            if (setter) {
                setter.call(obj, newVal)
            } else {
                val = newVal
            }
            dep.notify()
        }
    })
}

示例说明

我们在Vue实例中,通常会将data对象中的属性转化为响应式的数据,以便Vue可以检测到数据变化,从而实现视图自动更新。我们使用以下示例来说明Dep和Observer的用法:

// 假设我们有以下初始数据
const data = {
  name: 'John Smith',
  age: 35
}

// 将初始数据转换为Observer对象,实现数据的响应式
const observer = new Observer(data)

// 添加一个Watch实例来监控数据的变化
const watcher = new Watcher(() => {
  console.log('name changed:', data.name)
})

// 修改name属性的值
data.name = "Mary Johnson"

// 这时会触发watcher的update方法,在控制台输出: name changed: Mary Johnson

在这个示例中,我们通过将 data 对象转换为 Observer 对象来实现数据的响应式,然后创建Watcher对象来监控特定的数据变化,最后修改name属性的值时,watcher对象的update方法会被触发,从而在控制台输出新的值。

这样通过Dep和Observer的封装,我们可以很容易地实现 Vue 的响应式数据更新和视图重渲染。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue之Dep和Observer的用法及说明 - Python技术站

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

相关文章

  • java中对Redis的缓存进行操作的示例代码

    现在我将为您详细讲解如何在Java代码中对Redis缓存进行操作的完整攻略。 首先,我们需要确保已经在Java项目中引入了Redis的依赖包,例如Jedis或Lettuce等。 连接Redis服务 import redis.clients.jedis.Jedis; public class RedisDemo { public void connectRed…

    Vue 2023年5月28日
    00
  • vue 如何打开接口返回的HTML文件

    当我们向服务器请求数据时,有时候会返回HTML文件,而如果要在Vue中直接显示这个HTML文件,需要经过以下步骤: 1.使用axios发送请求获取HTML文件内容 首先,需要在Vue组件中引入axios,并使用axios发送一个GET请求来获取HTML文件内容。我们可以使用axios的get方法,指定请求的URL即可。 示例代码如下: import axio…

    Vue 2023年5月27日
    00
  • vue-router路由懒加载及实现的3种方式

    接下来我会针对“vue-router路由懒加载及实现的3种方式”进行详细讲解。整个过程分为以下几个步骤: 路由懒加载是什么? 路由懒加载是指延迟加载路由组件,当组件被访问时才会加载该组件,而不是一次性加载所有组件。 为什么要使用路由懒加载? 使用路由懒加载可以提升页面的加载速度,特别是在项目较大、组件较多的情况下,可以大幅减少首屏加载时间,提升用户体验。 实…

    Vue 2023年5月28日
    00
  • vue3+vite使用环境变量.env的一些配置情况详细说明

    下面是关于”vue3+vite使用环境变量.env的一些配置情况详细说明”的完整攻略。 简介 在Vue3和Vite开发环境中,使用环境变量可助力于管理不同的配置文件,例如本地开发环境、生产环境等。 当我们需要在不同的环境中配置不同的API地址、配置信息等时,使用环境变量便能够让我们的代码变得更加灵活通用。在这里,我们将详细说明如何在Vue3+Vite项目中使…

    Vue 2023年5月28日
    00
  • 详解vue中v-bind:style效果的自定义指令

    当我们使用 Vue 来开发前端应用时,我们经常需要动态地修改 DOM 元素的样式。Vue 中提供了 v-bind:style 这个指令来实现动态地绑定样式对象。 但是,当我们需要在多处使用相同的样式对象时,重复书写代码就会显得特别的繁琐,可读性也会大大降低,这时我们可以考虑将这个功能封装成自定义指令,在需要使用的地方直接引用指令即可。 下面就是一个完整的“详…

    Vue 2023年5月27日
    00
  • 微前端框架qiankun源码剖析之上篇

    微前端框架qiankun源码剖析之上篇 介绍 本篇文章将深入剖析微前端框架qiankun的源码,并且讨论它的工作原理和实现细节。qiankun是一个优秀的微前端解决方案,它可以帮助我们将多个独立的单页应用程序整合到一个整体中,从而实现一个统一的用户体验。在这篇文章中,我们将介绍qiankun的两大核心模块,分别是“qiankun”和“single-spa”,…

    Vue 2023年5月28日
    00
  • JS实现把鼠标放到链接上出现滚动文字的方法

    实现在鼠标放置在链接上时出现滚动文字的效果,可以使用JavaScript中的DOM事件和CSS的样式设置。 步骤1:编写HTML页面代码 首先,在HTML页面中创建一个链接元素,并设置该元素的class为“link”。 <a href="#" class="link">Roll over me</a&…

    Vue 2023年5月28日
    00
  • Vue中methods的this指向问题浅析

    下面是详细讲解“Vue中methods的this指向问题浅析”的完整攻略。 1. 什么是Vue中的methods? 在Vue组件里,methods是用于存放方法的一个对象。它可以包含各种实例方法,例如事件监听、异步请求等等。在组件内部可以通过this关键字来调用methods里面的方法。 2. methods中的this指向问题 在Vue中,methods中…

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