返回顶部
首页 > 资讯 > 精选 >vue3.0响应式函数原理是什么
  • 103
分享到

vue3.0响应式函数原理是什么

2023-06-29 04:06:51 103人浏览 八月长安
摘要

这篇文章将为大家详细讲解有关vue3.0响应式函数原理是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言:Vue3重写了响应式系统,和Vue2相比底层采用Proxy对象实现,在初始化的时候不需要遍历

这篇文章将为大家详细讲解有关vue3.0响应式函数原理是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

前言:

Vue3重写了响应式系统,和Vue2相比底层采用Proxy对象实现,在初始化的时候不需要遍历所有的属性再把属性通过defineProperty转换成get和set。另外如果有多层属性嵌套的话只有访问某个属性的时候才会递归处理下一级的属性所以Vue3中响应式系统的性能要比Vue2好。

接下来我们自己实现Vue3响应式系统的核心函数(Reactive/ref/toRefs/computed/effect/track/trigger)学习一下响应式原理。

首先我们使用Proxy来实现响应式中的第一个函数reactive

1.reactive

reactive接收一个参数,首先要判断这个参数是否是一个对象,如果不是直接返回,reactive只能将对象转换成响应式对象,这是和ref不同的地方。

接着会创建拦截器对象handler, 其中抱哈get,set,deleteProperty等拦截方法,最后创建并返回Proxy对象。

// 判断是否是一个对象const isObject = val => val !== null && typeof val === 'object'// 如果是对象则调用reactiveconst convert= target => isObject(target) ? reactive(target) : target// 判断对象是否存在key属性const haOwnProperty = Object.prototype.hasOwnPropertyconst hasOwn = (target, key) => haOwnProperty.call(target, key)export function reactive (target) {    if (!isObject(target)) {        // 如果不是对象直接返回        return target    }    const handler = {        get (target, key, receiver) {            // 收集依赖            const result = Reflect.get(target, key, receiver)            // 如果属性是对象则需要递归处理            return convert(result)        },        set (target, key, value, receiver) {            const oldValue = Reflect.get(target, key, receiver)            let result = true;            // 需要判断当前传入的新值和oldValue是否相等,如果不相等再去覆盖旧值,并且触发更新            if (oldValue !== value) {                result = Reflect.set(target, key, value, receiver)                // 触发更新...            }            // set方法需要返回布尔值            return result;        },        deleteProperty (target, key) {            // 首先要判断当前target中是否有自己的key属性            // 如果存在key属性,并且删除要触发更新            const hasKey = hasOwn(target, key)            const result = Reflect.deleteProperty(target, key)            if (hasKey && result) {                // 触发更新...            }            return result;        }    }    return new Proxy(target, handler)}

至此reactive函数就写完了,接着我们来编写一下收集依赖的过程。

在依赖收集的过程会创建三个集合,分别是targetMap,depsMap以及dep

其中targetMap是用来记录目标对象和字典他使用的是weakMap,key是目标对象,targetMap的值是depsMap, 类型是Map,这里面的key是目标对象的属性名称,值是一个Set集合,集合中存储的元素是Effect函数。因为可以多次调用同一个Effect在Effect访问同一个属性,这个时候这个属性会收集多次依赖对应多个Effect函数。

一个属性可以对应多个Effect函数,触发更新的时候可以通过属性找到对应的Effect函数,进行执行。

我们这里分别来实现一下effecttrack两个函数。

effect函数接收一个函数作为参数,我们首先在外面定一个变量存储callback, 这样track函数就可以访问到callback了。

let activeEffect = null;export function effect (callback) {    activeEffect = callback;    // 访问响应式对象属性,收集依赖    callback();    // 依赖收集结束要置null    activeEffect = null;}

track函数接收两个参数目标对象和属性, 他的内部要将target存储到targetMap中。需要先定义一个这样的Map。

let targetMap = new WeakMap()export function track (target, key) {    // 判断activeEffect是否存在    if (!activeEffect) {        return;    }    // depsMap存储对象和effect的对应关系    let depsMap = targetMap.get(target)    // 如果不存在则创建一个map存储到targetMap中    if (!depsMap) {        targetMap.set(target, (depsMap = new Map()))    }    // 根据属性查找对应的dep对象    let dep = depsMap.get(key)    // dep是一个集合,用于存储属性所对应的effect函数    if (!dep) {        // 如果不存在,则创建一个新的集合添加到depsMap中        depsMap.set(key, (dep = new Set()))    }    dep.add(activeEffect)}

track是依赖收集的函数。需要在reactive函数的get方法中调用。

get (target, key, receiver) {    // 收集依赖    track(target, key)    const result = Reflect.get(target, key, receiver)    // 如果属性是对象则需要递归处理    return convert(result)},

这样整个依赖收集就完成了。接着就要实现触发更新,对应的函数是trigger,这个过程和track的过程正好相反。

trigger函数接收两个参数,分别是target和key。

export function trigger (target, key) {    const depsMap = targetMap.get(target)    // 如果没有找到直接返回    if (!depsMap) {        return;    }    const dep = depsMap.get(key)    if (dep) {        dep.forEach(effect => {            effect()        })    }}

trigger函数要在reactive函数中的setdeleteProperty中触发。

set (target, key, value, receiver) {    const oldValue = Reflect.get(target, key, receiver)    let result = true;    // 需要判断当前传入的新值和oldValue是否相等,如果不相等再去覆盖旧值,并且触发更新    if (oldValue !== value) {        result = Reflect.set(target, key, value, receiver)        // 触发更新...        trigger(target, key)    }    // set方法需要返回布尔值    return result;},deleteProperty (target, key) {    // 首先要判断当前target中是否有自己的key属性    // 如果存在key属性,并且删除要触发更新    const hasKey = hasOwn(target, key)    const result = Reflect.deleteProperty(target, key)    if (hasKey && result) {        // 触发更新...        trigger(target, key)    }    return result;}

2.ref

ref接收一个参数可以是原始值也可以是一个对象,如果传入的是对象并且是ref创建的对象则直接返回,如果是普通对象则调用reactive来创建响应式对象,否则创建一个只有value属性的响应式对象。

export function ref (raw) {    // 判断raw是否是ref创建的对象,如果是直接返回    if (isObject(raw) && raw.__v__isRef) {        return raw    }    // 之前已经定义过convert函数,如果参数是对象就会调用reactive函数创建响应式    let value = convert(raw);    const r = {        __v__isRef: true,        get value () {            track(r, 'value')            return value        },        set value (newValue) {            // 判断新值和旧值是否相等            if (newValue !== value) {                raw = newValue                value = convert(raw)                // 触发更新                trigger(r, 'value')            }        }    }    return r}

3.toRefs

toRefs接收reactive函数返回的响应式对象,如果不是响应式对象则直接返回。将传入对象的所有属性转换成一个类似ref返回的对象将准换后的属性挂载到一个新的对象上返回。

export function toRefs (proxy) {    // 如果是数组创建一个相同长度的数组,否则返回一个空对象    const ret = proxy instanceof Array ? new Array(proxy.length) : {}    for (const key in proxy) {        ret[key] = toProxyRef(proxy, key)    }    return ret;}function toProxyRef (proxy, key) {    const r = {        __v__isRef: true,        get value () { // 这里已经是响应式对象了,所以不需要再收集依赖了            return proxy[key]        },        set value (newValue) {            proxy[key] = newValue        }    }    return r}

toRefs的作用其实是将reactive中的每个属性都变成响应式的。reactive方法会创建一个响应式的对象,但是如果将reactive返回的对象进行解构使用就不再

是响应式了,toRefs的作用就是支持解构之后仍旧为响应式。

4.computed

接着再来模拟一下computed函数的内部实现

computed需要接收一个有返回值的函数作为参数,这个函数的返回值就是计算属性的值,需要监听函数内部响应式数据的变化,最后将函数执行的结果返回。

export function computed (getter) {    const result = ref()    effect(() => (result.value = getter()))    return result}

computed函数会通过effect监听getter内部响应式数据的变化,因为在effect中执行getter的时候访问响应式数据的属性会去收集依赖,当数据变化会重新执行effect函数,将getter的结果再存储到result中。

关于“vue3.0响应式函数原理是什么”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

--结束END--

本文标题: vue3.0响应式函数原理是什么

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

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

猜你喜欢
  • vue3.0响应式函数原理是什么
    这篇文章将为大家详细讲解有关vue3.0响应式函数原理是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言:Vue3重写了响应式系统,和Vue2相比底层采用Proxy对象实现,在初始化的时候不需要遍历...
    99+
    2023-06-29
  • vue3.0响应式函数原理详细
    目录1.reactive2.ref3.toRefs4.computed前言: Vue3重写了响应式系统,和Vue2相比底层采用Proxy对象实现,在初始化的时候不需要遍历所有的属性再...
    99+
    2024-04-02
  • Vue数据响应式原理是什么
    本文小编为大家详细介绍“Vue数据响应式原理是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue数据响应式原理是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。响应式是什么简而言之就是数据变页面变如何实...
    99+
    2023-06-30
  • vue响应式原理是什么
    Vue 的响应式原理是通过数据劫持(Object.defineProperty)实现的,其核心思想是将数据模型和视图模型进行双向绑定...
    99+
    2023-05-13
    vue响应式原理 vue
  • Vue的响应式原理是什么
    本篇内容介绍了“Vue的响应式原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Depvar Dep = ...
    99+
    2023-06-20
  • Vue中响应式原理是什么
    这篇文章主要介绍“Vue中响应式原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Vue中响应式原理是什么”文章能帮助大家解决问题。响应式在日常开发中的应用是很常见的,这里举个简单的例子:le...
    99+
    2023-07-05
  • Vue3 Reactive响应式原理是什么
    一、怎么实现变量变化怎么实现变量变化,相关依赖的结果也跟着变化 当原本price=5变为price=20后total应该变为40,但是实际total并不会改变。 解决办法可以这样,当变量改变了,重新计算一次,那么结果就会改变为最新的结果。如...
    99+
    2023-05-21
    Vue3 reactive
  • Vue3的响应式原理是什么
    ProxyProxy这个核心API被Vue3的响应式原理所依赖,利用Proxy可以拦截一些对象操作。const obj = { a: 1 }; const p = new Proxy(obj, { get(target, propert...
    99+
    2023-05-24
    Vue3
  • Vue 中数据响应式的原理是什么
    Vue 中数据响应式的原理是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。改造数据我们先来尝试写一个函数,用于改造对象:为什么要先写这个函...
    99+
    2024-04-02
  • Vue.js中响应式的原理是什么
    今天就跟大家聊聊有关Vue.js中响应式的原理是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。关于Vue.jsVue.js是一款MVVM框架,上...
    99+
    2024-04-02
  • Vue2/Vue3的响应式原理是什么
    本篇内容主要讲解“Vue2/Vue3的响应式原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue2/Vue3的响应式原理是什么”吧!在讲解之前,我们先了解一下数据响应式是什么?所谓数据...
    99+
    2023-07-05
  • vue2.0/3.0中响应式的原理是什么
    本篇文章为大家展示了vue2.0/3.0中响应式的原理是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。vue是什么Vue是一套用于构建用户界面的渐进式JavaScript框架,Vue与其它大型框...
    99+
    2023-06-15
  • Vue响应式流程及原理是什么
    本文小编为大家详细介绍“Vue响应式流程及原理是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue响应式流程及原理是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、组件化流程1. 整个new Vue...
    99+
    2023-07-02
  • Vue.js中实现响应式的原理是什么
    Vue.js中实现响应式的原理是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一、Vue.js 响应式的使用现在有个很简单的需求,点击页面...
    99+
    2024-04-02
  • Vue 3中响应式的实现原理是什么
    本篇文章给大家分享的是有关Vue 3中响应式的实现原理是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1. 实现响应式响应基本类型变量首先...
    99+
    2024-04-02
  • Vue中响应式系统实现原理是什么
    本篇内容介绍了“Vue中响应式系统实现原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!框架每个组件实例都会对应一个watcher实例...
    99+
    2023-07-05
  • Vue3.0插件执行原理是什么
    这篇文章主要介绍“Vue3.0插件执行原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Vue3.0插件执行原理是什么”文章能帮助大家解决问题。一、编写插件Vue项目能够使用很多插件来丰富自己...
    99+
    2023-06-29
  • PHP 数组响应函数是什么?
    在 PHP 中,数组是一种非常常见且重要的数据类型。数组可以存储多个值,并且可以通过索引或关联键来访问这些值。在 PHP 中,有许多数组响应函数可用于操作数组。在本文中,我们将介绍数组响应函数是什么,并展示一些常见的数组响应函数以及它们的...
    99+
    2023-09-02
    数组 响应 函数
  • vue3响应式原理和api编写的方法是什么
    这篇文章主要讲解了“vue3响应式原理和api编写的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue3响应式原理和api编写的方法是什么”吧!前言vue3响应式原理加api编写...
    99+
    2023-06-22
  • vue.js数据响应式原理解析
    目录Object.defineProperty()定义 defineReactive 函数递归侦测对象的全部属性流程分析observe 函数Observer 类完善 defineRe...
    99+
    2022-11-13
    vue.js数据响应式原理 vue.js数据响应式
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作