VueJS设计与实现之浅响应与深响应详解

正文

前文中讲完了如何响应Object,并处理了一些响应中的问题,但是我们目前,包括之前实现的响应式,其实只是浅响应。

直接上代码

const obj = {a:{b:1}}
const reactive = (obj)=> new Proxy(obj,{
 get(target,key,receiver){
   /*省略其他逻辑*/
  return Reflect.get(target,key,receiver)
 },
  /*省略其他拦截*/
})
const data = reactive(obj)

问题就出现在Reflect.get(target, key, receiver)这句代码里,我们现在尝试一下获取data.a,应该返回的是{b:1},不是Proxy,自然不会响应什么。

所以对于这种嵌套对象,我们自然要去递归的把对象转换为响应式对象。

const reactive = (obj)=> new Proxy(obj,{
 get(target,key,receiver){
   /*省略其他逻辑*/
  const res =  Reflect.get(target,key,receiver)
  if(res && typeof res === 'object'){
      return reactive(res)
  }
  return res
 },
 /*省略其他拦截*/
})

这样,当内部是嵌套对象的时候,我们递归把嵌套对象转换为响应式对象,这样再按之前的追踪依赖,触发响应去处理就好了。

当时,深响应和浅响应都是有各自的使用条件的。比如我在完成第一个vue3.2项目有感中写过,我就比较喜欢用shallowRef,这就是一种浅响应。

好了,话题收回来。我们之前封装的那个reactive已经变成一个深响应了,我们现在就在封装一层,去区分浅响应和深响应。我们通过一个新的参数deepify去判断浅响应和深响应,然后深响应的时候才去递归。

之所以再封装了一层,是因为我们后续还要继续扩展这个函数

const createReactive = (obj,deepify = true)=>new Proxy(obj,{
 get(target,key,receiver){
   /*省略其他逻辑*/
  const res =  Reflect.get(target,key,receiver)
  //深响应式递归
  if(deepify && res && typeof res === 'object'){
       return reactive(res)
  }
  return res
 },
 /*省略其他拦截*/
})

这样子封装之后,我们就有了2个函数reactive,shallowReactive

const reactive = (obj)=>createReactive(obj)
const shallowReactive = (obj)=>createReactive(obj,false)

大家使用的时候,其实需要看情况去选择,浅响应其实有时候比深响应更方便。就比如我之前在那篇文章中举得例子一样。

以上就是VueJS设计与实现之浅响应与深响应详解的详细内容,更多关于VueJS浅响应深响应的资料请关注我们其它相关文章!

(0)

相关推荐

  • vue中provide inject的响应式监听解决方案

    目录 provide inject的响应式监听解决 vue监听赋值及provide与inject provide inject的响应式监听解决 提示:provide 和 inject 绑定并不是可响应的.这是刻意为之的.然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的. 所以传值传对象即可 provide(){     return {       provObj: {         uuidList:{}       }     }   }, this._provided.p

  • Vuejs第一篇之入门教程详解(单向绑定、双向绑定、列表渲染、响应函数)

    什么是组件? 组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能.在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展. 接下来给大家介绍vuejs单向绑定.双向绑定.列表渲染.响应函数基础知识,具体详情如下所示: (一)单向绑定 <div id="app"> {{ message }} </div> <sc

  • 代码详解Vuejs响应式原理

    响应式原理 > vuejs中的模型(model)和视图(view)是保持同步的,在修改数据的时候会自动更新视图,这其实依赖于Object.defineProperty方法,所以vuejs不支持IE8及以下版本,vuejs通过劫持getter/setter方法来监听数据的变化,通过getter进行依赖收集,在数据变更执行setter的时候通知视图更新. Object.defineProperty > Object.defineProperty可以定义对象的属性或修改对象的属性 > 目前可以

  • vue3结构赋值失去响应式引发的问题思考

    目录 前言 原始值的响应式系统的实现 为什么ES6 解构,不能随意使用会破坏他的响应式特性 proxy背景 实现原理 解构 props 对象,因为它会失去响应式 直接赋值reactive响应式对象 vuex中组合API赋值 结语 前言 vue3发布以来经历两年风头正盛,现在大有和react 平分天下的势头,我们知道他是基于proxy 实现响应式的能力, 解决了vue2所遗留下来的一些问题,同时也正由于proxy的特性,也提高了运行时的性能 凡事有利有弊, proxy虽然无敌,但是他也有本身的局限

  • vue3中defineProps传值使用ref响应式失效详解

    子组件接收父组件的传参. 父组件: <template> <Son :data="data"/> </template> <script setup> import { ref } from "vue"; let data = ref('hello') setTimeout(() => { data.value = 'how are you doing' }, 2000) </script> 子组件:

  • vuejs响应用户事件(如点击事件)

    需求: 页面上的列表原先有3个,我们想点击一次添加一条记录,也可以在头和尾删除数据: 我们也可以删除我们想删除的任意一行记录: 如果是用传统的jquery操作,页面中js会特别多,而且操作也很麻烦. 这里用vue.js就非常简单. 我们先看页面效果: 页面初始化.png 末尾增加一项.png 删除项.png 再来看代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT

  • C++对象的浅复制和深复制详解及简单实例

    C++对象的浅复制和深复制详解及简单实例 浅复制:两个对象复制完成后共享某些资源(内存),其中一个对象的销毁会影响另一个对象 深复制:两个对象复制完成后不会共享任何资源,其中一个对象的销毁不会影响另一个对象 下面我们来看一段代码,以便直观的理解: #include<iostream> #include<string.h> using namespace std; class Student { int no; char *pname; public: Student(); Stud

  • VueJS设计与实现之浅响应与深响应详解

    正文 前文中讲完了如何响应Object,并处理了一些响应中的问题,但是我们目前,包括之前实现的响应式,其实只是浅响应. 直接上代码 const obj = {a:{b:1}} const reactive = (obj)=> new Proxy(obj,{ get(target,key,receiver){ /*省略其他逻辑*/ return Reflect.get(target,key,receiver) }, /*省略其他拦截*/ }) const data = reactive(obj)

  • 基于rem的移动端响应式适配方案(详解)

    视口 在前一段时间,我曾经写过一篇关于viewport的文章.最近由于在接触移动端开发,对viewport有了新的理解.于是,打算重新写一篇文章,介绍移动端视口的相关概念. 关于这篇文章说到的所有知识,本质上离不开以下代码 <meta name="viewport" content="width=device-width, initial-scala=1, maximum-scale=1, minimum-scale=1, user-scalable=no"

  • vuejs动态组件给子组件传递数据的方法详解

    通过子组件定义时候的props可以支持父组件给子组件传递数据,这些定义的props在子组件的标签中使用绑定属性即可,但是如果使用的是<component>动态组件,这个时候就没有显式的子组件标签,要给子组件传递数据需要在<component> 中进行绑定 <div class="app" id="deviceready"> <component :is="currentView" :user_name.s

  • Vuejs第十一篇组件之slot内容分发实例详解

    什么是组件? 组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能.在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展. Slot分发内容 ①概述: 简单来说,假如父组件需要在子组件内放一些DOM,那么这些DOM是显示.不显示.在哪个地方显示.如何显示,就是slot分发负责的活. ②默认情况下 父组件在子组件内套的内容,是不显示的. 例如代码: <

  • JavaWeb Refresh响应头代码实例详解

    这篇文章主要介绍了JavaWeb Refresh响应头代码实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.Refresh响应头:可以理解为定时的重定向,在指定的时间后发生页面的跳转 二.代码示例: package cn.xxx.Servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.Ht

  • Laravel 修改验证异常的响应格式实例代码详解

    Laravel 默认验证不通过后响应格式如下,有时此格式并不满足自己要求,需要修改格式. // status 422 { "message":"The given data was invalid.", "errors":{ "url":[ "url 无效的格式" ] } } 当 Request 验证失败时会抛出 ValidationException异常,最终交由全局异常Handler类处理.Handle

  • SpringBoot中的响应式web应用详解

    简介 在Spring 5中,Spring MVC引入了webFlux的概念,webFlux的底层是基于reactor-netty来的,而reactor-netty又使用了Reactor库. 本文将会介绍在Spring Boot中reactive在WebFlux中的使用. Reactive in Spring 前面我们讲到了,webFlux的基础是Reactor. 于是Spring Boot其实拥有了两套不同的web框架,第一套框架是基于传统的Servlet API和Spring MVC,第二套是

  • java面向对象设计原则之单一职责与依赖倒置原则详解

    目录 单一职责概念 实现 拓展 依赖倒置原则概念 示例 拓展 单一职责概念 不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,否则就应该把类拆分.交杂不清的职责将使得代码牵一发而动全身,导致代码混涩难懂,不易修改.难以扩展和复用.如:以前开发C/S程序中的胖客户端程序,就是将人机交互逻辑.业务加工处理逻辑和数据库操作逻辑混合在一起. 实现 单一职责原则是进行类的划分和封装的基本原则,进行类的具体抽象.尽量做到,类的功能单一和清晰化. 1.根据机能划分,使用封装来创建对象之间的分

  • Vue3 Reactive响应式原理逻辑详解

    目录 前言 一.怎么实现变量变化 二.怎么实现变量变化 三.将多个dep存储在Map中 四.将多个object的depsMap继续存储起来 五.核心 六.源码解析(TypeScript) 前言 本篇文章主要讲解vue响应式原理的逻辑,也就是vue怎么从最开始一步步推导出响应式的结构框架. 先从头构建一个简单函数推导出Vue3的Reactive原理,最后再进行源码的验证. 一.怎么实现变量变化 怎么实现变量变化,相关依赖的结果也跟着变化 当原本price=5变为price=20后total应该变为

随机推荐