iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > 其他 >深入浅析vue处理响应式数据的方法
  • 882
分享到

深入浅析vue处理响应式数据的方法

前端Vue.js 2023-05-14 22:05:38 882人浏览 安东尼
摘要

本篇文章带大家学习Vue,聊聊vue如何处理响应式数据?希望对大家有所帮助!关于vue的响应式数据,你可能有很多疑惑。比如为什么要改用proxy?比如为什么有reactive和ref两个api?比如vue是如何实现响应式的?其实这些在源码中

本篇文章带大家学习Vue,聊聊vue如何处理响应式数据?希望对大家有所帮助!

深入浅析vue处理响应式数据的方法

关于vue的响应式数据,你可能有很多疑惑。

比如为什么要改用proxy?

比如为什么有reactive和ref两个api?

比如vue是如何实现响应式的?

其实这些在源码中,都能找到答案。

在第一篇vue3有哪些升级中,我也提了一下使用proxy的好处,以及Object.defineProperty的缺陷。但是今天,我想换个角度,让chatGPT来回答一下这个问题。【相关推荐:vuejs视频教程WEB前端开发

嗯,我感觉比我总结的好。

image.png

那继续下一个问题。

image.png

这个回答感觉就比较官方了,没有回答到我想要的答案。

理由其实很简单,因为proxy方法不能代理值类型,只能代理对象。所以需要一个额外的方法,来处理值类型的数据。

当然你也可以一个ref走天下,vue源码做了兼容会自动进行转换

有了这些理解之后,我们来看今天的重头戏,自己仿照vue3源码,实现一个响应式系统。

相关代码可以点击查看,根据文章的标题选择不同的分支即可。

实现Reactive

在前文我们也介绍了,reactive其实用的是proxy代理对象。

我们可以使用proxy实现一个简单的代理函数reactive。

      function reactive(target) {        const isObject = (val) =>  val !== null && typeof val === 'object'

        if (!isObject(target)) {          console.warn(`数据必须是对象: ${String(target)}`)          return target
        }        const proxy = new Proxy(target, {          get: (target, key, receiver) => {            console.log('get', key)            const res = Reflect.get(target, key, receiver)            // track(target, key)
            // 这句很关键,不然嵌套数据,里面的不会响应
            if (isObject(res)) {              return reactive(res)
            }            return res
          },          set: (target, key, value, receiver) => {            console.log('set', key, value)            const result = Reflect.set(target, key, value, receiver)            // trigger(target, key, value)
            return result
          },          deleteProperty: () => {            const result = Reflect.deleteProperty(target, key)            return result
          }
        })        return proxy
      }      const person = reactive({        name: '',        age: 18,        like: ['apple']
      })

      person.name  = 'vue test'复制代码

注意:Reflect

Reflect.get(target, key)跟直接访问target[key]是有一点差别的。

当代理对象中,有get,set等this指向的时候,可以重定向this。

举个例子:

        const person = new Proxy({            name: "vue test",            age: 18,            get info() {                return 'name is :' + this.name + ' age is:' + this.age
            }
        }, {            get: (target, key, receiver) => {                console.log('get', key)                // return target[key]
                return Reflect.get(target, key, receiver)
            }
        })        console.log(person.info)复制代码

使用Reflect,我们在访问name, age的时候均可以触发。image.png

改成target之后,则只会在info触发一次。

return target[key]复制代码

image.png

实现ref

在vue3中,ref是通过get和set来实现的。

跟上面类似,也还是先声明一个函数,然后通过get,set来访问数据。

      function ref(value) {        return new RefImpl(value)
      }      class RefImpl {        constructor(value) {          // 如果值是对象,则用reactive处理
          this._value = isObject(value) ? reactive(value) : value          // 记录一下初始值
          this._rawValue = value
        }        get value() {          // trackRefValue(this)
          return this._value
        }        set value(newVal) {          if (!Object.is(newVal, this._rawValue)) {            // 更新原始数据
            this._rawValue = newVal            // 更新 .value 的值
            this._value = isObject(newVal) ? reactive(newVal) : value            // triggerRefValue(this)
          }
        }
      }复制代码

源码也很直观的解释了,为什么ref的使用一定要用.value的方式使用,因为get/set就是通过value来设置的。

添加依赖收集与触发

数据代理我们已经完成了,但是数据更改之后,怎么通知组件实现双向绑定呢?

答案就是依赖收集与触发,也就是当触发get的时候,我把触发get的这个条件【函数】给保存起来,当触发set的时候,重新执行一下触发一下这个条件【函数】不就行了吗。

还是来看代码,我加一个track收集的方法,加一个target触发的方法。(也就是上面代码片段注释掉的两行代码)

除此之外,还需要一个effect函数来管理触发函数。

      let activeEffect = null
      const targetMap = new WeakMap()      // 依赖收集/触发
      function track(target, key) {        let depsMap = targetMap.get(target)        if (!depsMap) {
          targetMap.set(target, (depsMap = new Map()))
        }        let dep = depsMap.get(key)        if (!dep) {
          dep = new Set()
        }
        dep.add(activeEffect)
        depsMap.set(key, dep)
      }      function trigger(target, key, value) {        const depsMap = targetMap.get(target)        if (!depsMap) {          return
        }        const deps = depsMap.get(key)        if (!deps) {          return
        }

        deps.forEach(effectFn => {          if (effectFn.scheduler) {
            effectFn.scheduler()
          } else {            effectFn()
          }
        })
      }      function effect(fn,options = {}) {        const effectFn = () => {          try {
            activeEffect = effectFn            return fn()
          } catch (error) {
            activeEffect = null
          }
        }        if (!options.lazy) {          effectFn()
        }
        effectFn.scheduler = options.scheduler
        return effectFn
      }      const person = reactive({        name: "hello world"
      })      effect(() => {        console.log('effect person', person.name)
      })      setTimeout(() => {
        person.name = 'setTimeout world'
      }, 2000)复制代码

activeEffect用来存触发的条件函数。

targetMap用来存放依赖字典,格式如下

{
    target: {
        key: []
    }
}复制代码

输出结果为hello world,2秒之后,重新执行依赖性函数,输出setTimeout world

image.png

总结

数据的代理并不复杂,就是在proxy的基础上,加上一些边界处理。而要实现响应式则需要加上依赖收集,依赖触发的实现。

effect是一个很重要的函数,很多api是基于这个函数开发的,比如useEffect, watch。组件的更新也是基于effect函数,这个后续还会提到。

如果不太理解effect,可以梳理一下执行顺序。

  • 1.调用effect函数,并传入参数fn
  • 2.申明一个effectFn函数,并执行,将函数保存为activeEffect
  • 3.执行fn,读取person.name
  • 4.走proxy的get代理
  • 5.收集依赖,将activeEffect保存的函数存到全局map中
  • 6.此时,effect函数执行完毕,等待数据更新
  • 7.2s后,走proxy的set代理
  • 8.执行全局map中保存的函数,重新执行effect函数,再次回到步骤1

相关代码可以点击查看,选择lesson3分支即可。

文章相关代码,可在vue/examples中查看,仿vue实现版本可在packages/reactivity中查看。

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

以上就是深入浅析vue处理响应式数据的方法的详细内容,更多请关注编程网其它相关文章!

--结束END--

本文标题: 深入浅析vue处理响应式数据的方法

本文链接: https://www.lsjlt.com/news/207154.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 深入浅析vue处理响应式数据的方法
    本篇文章带大家学习vue,聊聊vue如何处理响应式数据?希望对大家有所帮助!关于vue的响应式数据,你可能有很多疑惑。比如为什么要改用proxy比如为什么有reactive和ref两个api比如vue是如何实现响应式的?其实这些在源码中,都...
    99+
    2023-05-14
    前端 Vue.js
  • 深入理解Vue的数据响应式
    目录1. ES语法的getter和setter2. ES语法的 defineProperty3. Vue对数据的代理和监听4. Vue的数据响应式1. ES语法的getter和set...
    99+
    2022-11-12
  • vue响应式原理与双向数据的深入解析
    了解object.defineProperty 实现响应式 清楚 observe/watcher/dep 具体指的是什么 了解 发布订阅模式 以及其解决的具体问题 在Javascri...
    99+
    2022-11-12
  • Vue深入讲解数据响应式原理
    目录响应式是什么如何实现数据响应式实现对象属性拦截通用的劫持方案总结响应式是什么 简而言之就是数据变页面变 如何实现数据响应式 在Javascript里实现数据响应式一般有俩种方案,...
    99+
    2022-11-13
  • vue处理响应式数据的方法是什么
    这篇“vue处理响应式数据的方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“vue处理响应式数据的方法是什么”文章吧...
    99+
    2023-07-05
  • 深入浅析java中的数据处理机制
    这篇文章给大家介绍深入浅析java中的数据处理机制,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。MyFile .java:import java.io.BufferedReader;import java.io.Fil...
    99+
    2023-05-31
    java 数据处理机制 ava
  • Vue双向数据绑定与响应式原理深入探究
    目录一、双向数据绑定和数据响应式是相同的吗二、双向数据绑定的原理三、数据响应式的原理与实现一、双向数据绑定和数据响应式是相同的吗 不相同,原因如下: 响应式是指通过数据区驱动DOM视...
    99+
    2022-11-13
    Vue 双向数据绑定 Vue 响应式原理
  • vue3.x源码剖析之数据响应式的深入讲解
    目录前言什么是数据响应式数据响应式的大体流程vue2.x数据响应式和3.x响应式对比大致流程图实现依赖收集代码仓库结尾前言 如果错过了秋枫和冬雪,那么春天的樱花一定会盛开吧。最近一直...
    99+
    2022-11-13
  • 深入探讨Golang中的数据处理方法
    深入探讨Golang中的数据处理方法导言:在当今的信息时代,数据是无处不在的。对于开发者来说,处理数据是日常工作中不可或缺的一部分。而Go语言(Golang)作为一种强大且高效的编程语言,提供了许多灵活且易用的数据处理方法。本文将深入探讨G...
    99+
    2023-12-23
    方法 Golang 数据处理
  • vue数据响应式原理中数组的示例分析
    这篇文章主要介绍vue数据响应式原理中数组的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!src/core/observer/index.jssrc/core/observer/array.js arrayM...
    99+
    2023-06-29
  • 怎么浅析RAID0/1安全差别及处理数据安全的应对方式
    这篇文章将为大家详细讲解有关怎么浅析RAID0/1安全差别及处理数据安全的应对方式,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。【RAID0/1分析背景】基于之前接到用户的委托,萌生想要尝试...
    99+
    2023-06-04
  • SpringBoot响应处理之以Json数据返回的实现方法
    目录一、示例代码二、返回值解析原理三、源代码分析(debug)四、内容协商机制1. 内容协商2. 内容协商原理重点源代码3. HttpMessageConverters消息转换器原理...
    99+
    2022-11-13
  • 响应速度更快的大数据处理方法,你需要了解!
    随着信息时代的到来,数据已经成为了我们生活中不可或缺的一部分。而随着数据的不断增长,我们需要更加高效的方法来处理大数据,以便更好地挖掘数据价值。本文将为大家介绍响应速度更快的大数据处理方法,让你了解如何更好地处理大数据。 一、传统的大数据处...
    99+
    2023-06-26
    响应 大数据 numpy
  • Java中的响应式编程:如何利用异步方式处理不同的数据类型?
    响应式编程是一种处理异步和事件驱动程序的编程范式,它可以极大地提高程序的性能和可扩展性。Java中的响应式编程是一种基于流的编程方式,可以让我们更加高效地处理不同类型的数据。在本文中,我们将介绍Java中的响应式编程及其使用。 一、什么是...
    99+
    2023-10-21
    数据类型 响应 异步编程
  • 处理大数据:Python 中哪些存储和响应方法最适合您的需求?
    在当今数字化时代,数据量的增长速度迅猛,对数据的处理与分析需求也日益增加。Python 作为一种强大的编程语言,越来越受到数据科学家和分析师的青睐。在 Python 中,有许多存储和响应方法可供选择,但哪种方法最适合您的需求?在本文中,我...
    99+
    2023-06-27
    存储 响应 大数据
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作