再说vue响应式数据

  • 请说一下你对响应式数据的理解
    • 如何实现响应式数据据
      • 对象
        • vue2 响应式核心代码
      • 数组
    • vue2 处理缺陷
    • Vue3则采用 proxy
      - vue3 响应式核心代码

请说一下你对响应式数据的理解

如何实现响应式数据据

数组和对象类型当值变化时如何劫持到。

对象

对象内部通过defineReactive方法,使用object.defineProperty将属性进行劫持(只会劫持已经存在的属性)

多层对象是通过递归来实现劫持。

vue2 响应式核心代码
let obj = {
    name:'jw' , 
    age:30,
    n: {
        num: 000
    }
};

// 定义相应式函数
function defineReactive(target,key,value){
    // 判断检测对象中是否有嵌套对象
    observer(value)

    object.defineProperty(target, key,{
        get(){
            return value
        },
        set(newValue){
            if(value !== newValue){
                value = newValue;
                // 判断心智是否有是对象
                observer(newValue)
            } 
        } 
    }) 
}

// 定义观察函数
function observer(data){
    // 如果不是对象或者数据为空,直接返回
    if(typeof data !== "object" || typeof data == null){
        return data
    }

    // 循环执行第一层数据
    for(let key in data){
        defineReactive(data, key , data[key])
    }
}

observer(obj) 
数组

数组则是通过重写数组方法来实现。

Vue2中数组的响应式更新没有使用Object.defineProperty,而是采用了一种特殊的技术。

使用Object.defineProperty可以定义对象属性的获取(get)和设置(set)方法,从而实现对属性的拦截和控制。然而,对于数组来说,它只能拦截并控制数组对象本身的变化,而不能直接拦截数组元素的变化。

因此,如果使用Object.defineProperty来实现数组的响应式,需要对数组的每一个索引进行拦截,监听其变化并触发更新,这样会带来很大的性能开销和复杂度。

为了解决这个问题,Vue2采用了数组的变异方法(mutation method)来触发响应式更新。

这些变异方法,如pushpopshiftunshiftsplicesortreverse,在执行时会被重写,以便在修改数组时同时触发响应式更新。

以下几个数组方法会被重写以实现响应式:

  1. push():向数组末尾添加一个或多个元素。
  2. pop():删除并返回数组的最后一个元素。
  3. shift():删除并返回数组的第一个元素。
  4. unshift():向数组的开头添加一个或多个元素。
  5. splice():从指定位置插入、删除或替换元素。
  6. sort():对数组进行排序。
  7. reverse():颠倒数组中元素的顺序。

当调用这些方法时,Vue2会拦截它们的调用,并执行以下操作:

  1. 在Vue初始化阶段: Vue2会对data选项中的数组进行遍历,并重写数组的变异方法。
  2. 更新依赖:Vue2会更新依赖于该数组的视图或计算属性。
  3. 触发响应:Vue2会通知相关组件进行重新渲染。

通过重写数组变异方法,Vue2能够在数组被修改时,及时地通知相关组件进行更新,从而实现数组的响应式。

需要注意的是,这种方式只能拦截变异方法的调用,而无法拦截直接通过索引修改数组元素的方式。如果需要修改数组中的某个元素,并触发响应式更新,需要使用Vue提供的特定方法,比如$setVue.set方法。

var vm = new Vue({
  data: {
    list: ['apple', 'banana', 'orange']
  }
})

// 修改数组,触发响应式更新
vm.list.push('grape');
// 视图会自动更新,list中的元素会显示为['apple', 'banana', 'orange', 'grape']

// 直接通过索引修改数组元素,不会触发响应式更新
vm.list[0] = 'watermelon';
// 视图不会自动更新,list中的元素仍然显示为['apple', 'banana', 'orange', 'grape']

// 使用Vue.set方法修改数组元素,触发响应式更新
Vue.set(vm.list, 0, 'watermelon');
// 视图会自动更新,list中的元素会显示为['watermelon', 'banana', 'orange', 'grape']

更多详细内容,请微信搜索“前端爱好者戳我 查看

vue2 处理缺陷

  • 在Vue2 的时候使用 defineProperty 来进行数据的劫持,需要对属性进行重写添加getter及setter 性能差
  • 当新增属性和删除属性时无法监控变化。需要通过$set、 $delete实现
  • 数组不采用 defineproperty 来进行劫持 (浪费性能,对所有索引进行劫持会造成性能浪费)需要对数组单独进行处理
  • 对于 ES6 中新产生的 Map、Set 这些数据结构不支持

Vue3则采用 proxy

Vue2 不采用 proxy,因为浏览器兼容

vue3 响应式核心代码
let obj = {
    name:'jw' , 
    age:30,
    n: {
        num: 000
    }
};

let handler = {
    get(target, key) { 
        // 在访问属性时进行依赖收集
        let temp = target[key]
        
        // 如果值是对象,则递归监听
        if(typeof temp=== "object"){
            return new Proxy(temp, handler)
        } 

        // 否则直接返回
        return temp 
    },
    set(target, key, value) { 
        // 在更新属性时触发依赖更新
        target[key] = value
    }, 
}

function reactive(target) {
  return new Proxy(target, handler);
} 

const proxy = reactive(obj)

reactive函数接受一个普通对象作为参数,并返回一个经过代理的响应式对象。

这个代理对象利用Proxy的get和set方法来拦截属性的读取和修改操作,并触发相应的依赖收集和更新。

复杂实例

在Vue 3中,可以使用Proxy对象来实现响应式实例。

Proxy是ES6引入的新特性,它可以拦截并自定义对象的操作。

下面是一个使用Proxy实现响应式实例的示例:

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      // 在访问属性时进行依赖收集
      track(target, key);
      return Reflect.get(target, key);
    },
    set(target, key, value) {
      // 在更新属性时触发依赖更新
      const oldValue = target[key];
      const result = Reflect.set(target, key, value);
      if (oldValue !== value) {
        trigger(target, key);
      }
      return result;
    },
    deleteProperty(target, key) {
      // 在删除属性时触发依赖更新
      const hasKey = Object.prototype.hasOwnProperty.call(target, key);
      const result = Reflect.deleteProperty(target, key);
      if (hasKey) {
        trigger(target, key);
      }
      return result;
    }
  });
}

在上述代码中,reactive函数接受一个普通对象作为参数,并返回一个经过代理的响应式对象。这个代理对象利用Proxygetset方法来拦截属性的读取和修改操作,并触发相应的依赖收集和更新。

需要注意的是,上述代码中的tracktrigger函数是为了配合依赖收集和更新使用的,它们在实际应用中需要根据具体场景进行实现。

使用上述的reactive函数,我们可以将一个普通对象转换成响应式实例。例如:

const user = reactive({
  name: 'Alice',
  age: 25
});

console.log(user.name); // 输出:'Alice'

user.age = 26; // 触发依赖更新

通过reactive函数创建的user对象就是一个响应式实例了。当访问user对象的属性时,会自动进行依赖收集;当更新属性的值时,会触发相应的依赖更新。这样就实现了Vue 3中的响应式机制。

由于Proxy是ES6的新特性,不支持的浏览器可能无法正常运行上述代码。

在实际开发中,可以使用Babel等工具进行转换,以兼容不同的浏览器环境。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/536096.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何将普通maven项目转为maven-web项目

文件-项目结构(File-->Project Structure ) 模块-->learn(moudle-->learn) 选中需要添加web的moudle,点击加号,我得是learn,单击选中后进行下如图操作: 编辑路径 结果如下…

Centos7 k8s 集群 - Rook Ceph 安装

环境准备 基础环境 系统名称操作系统CPU内存硬盘Kubernete 版本Docker版本IPmasterCentos74c4gsdb 20G1.17.023.0.1192.168.1.128node01Centos74c4gsdb 20G1.17.023.0.1192.168.1.129node02Centos74c4gsdb 20G1.17.023.0.1192.168.1.130node03Centos74c4gsdb 20G1.17.023.0.1…

OpenHarmony4.0分布式任务调度浅析

1 概述 OpenHarmony 分布式任务调度是一种基于分布式软总线、分布式数据管理、分布式 Profile 等技术特性的任务调度方式。它通过构建一种统一的分布式服务管理机制,包括服务发现、同步、注册和调用等环节,实现了对跨设备的应用进行远程启动、远程调用、…

3d怎么按路径制作模型---模大狮模型网

在3D建模中,按路径制作模型是一种常见的技术,特别适用于创建曲线、管道、绳索等线性形状的物体。虽然这项技术可能对初学者来说有些复杂,但通过一步步的指导和实践,你将能够掌握它。本文将详细介绍按路径制作模型的步骤&#xff0…

OpenDDS-3.27构建与用法

一、OpenDDS-3.27构建 ./configure To enable Java bindings, use ./configure --java make 二、运行Messenger Example: source setenv.sh For the C example:cd DevGuideExamples/DCPS/Messenger For the Java example:cd java/tests/mes…

【JVM】JVM堆占用情况分析(频繁创建的对象、内存泄露等问题)、jmap+jhat、jvisualvm工具使用

文章目录 一. 相关命令1. 查看进程堆内存整体使用情况:OOM的可能2. 统计类的对象数量以及内存占用:定位内存泄漏 二. 分析内存占用1. 使用 jhat 排查对象堆占用情况1.1. 排查步骤1.2. 具体分析例子a. 分析频繁创建对象导致的OOM 1.3. OQL查看某一个对象的…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十 简单视频浮雕画效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十 简单视频浮雕画效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之十 简单视频浮雕画效果 一、简单介绍 二、简单视频浮雕画效果实现原理 三、简单视频浮雕画效果…

关于MCU产品开发参数存储的几种方案

关于MCU产品开发参数存储的几种方案 Chapter1 关于MCU产品开发参数存储的几种方案Chapter2 单片机参数处理[保存与读取]Chapter3 嵌入式设备参数存储技巧Chapter4 STM32硬件I2C的一点心得(AT24C32C和AT24C64C) Chapter1 关于MCU产品开发参数存储的几种方案 原文链接 在工作中…

Python 批量检测ip地址连通性,以json格式显示(支持传参单IP或者网段)

代码 ########################################################################## File Name: check_ip_test.py# Author: eight# Mail: 18847097110163.com # Created Time: Thu 11 Apr 2024 08:52:45 AM CST################################################…

突破界限 千视将在 NAB 2024 展会上展示领先的 AV over IP 技术

突破界限!千视将在 NAB 2024 展会上展示领先的 AV over IP技术 作为AV over IP领域的先驱者,Kiloview将于2024年4月14日至17日在NAB展会(展台号:SU6029)隆重登场,展示我们领先业界的AV over IP产品、解决方…

Windows下安装GPU版Pytorch

升级Driver到最新版本 Windows搜索栏中输入设备管理器找到显示适配器一项,点击展开,你将看到你的NVIDIA显卡列在其中右键点击你的NVIDIA显卡,选择更新驱动软件…。在弹出的对话框中,选择自动搜索更新的驱动软件。之后&#xff0c…

nginx反向代理conf

打开nginx配置。 对登录功能测试完毕后,接下来,我们思考一个问题:前端发送的请求,是如何请求到后端服务的? 前端请求地址:http://localhost/api/employee/login 后端接口地址:http://localho…

计算机网络——NAT技术

目录 前言 前篇 引言 SNAT(Source Network Address Translation)源网络地址转换 SNAT流程 确定性标记 DNAT(Destination Network Address Translation,目标网络地址转换) NAT技术重要性 前言 本博客是博主用于…

ShardingSphere再回首

概念: 连接:通过协议 方言及库存储的适配,连接数据和应用,关注多模数据苦之间的合作 增量:抓取库入口流量题提供重定向, 流量变形(加密脱敏)/鉴权/治理(熔断限流)/分析等 可插拔:微内核 DDL:cr…

ssm+vue的实验室课程管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频: ssmvue的实验室课程管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构…

来补上LangChain的CookBook(二)

LangChain Experssion Language 简称LCEL,感觉就是为了节省代码量,让程序猿们更好地搭建基于大语言模型的应用,而在LangChain框架中整了新的语法来搭建promptLLM的chain。来,大家直接看官网链接:LangChain Expression …

pandas(day10)

一. 各各品类产品交易指数对比 获取文件名 files glob.glob("./*.xlsx")# 读取数据,并改列名,增加一列 品牌 dfs [] for f in files:t f[2:4]df pd.read_excel(f)df["品牌"] tif t "拜耳":df.rename(columns{"…

C语言读取 .ico 文件并显示数据

原来是想做光标编辑器&#xff0c;自己把绘图板的内容导出为光标格式 鼠标指针文件格式解析——Windows&#xff08;一&#xff09; (qq.com) 代码来源自 Icons | Microsoft Learn 鄙人又补充些变量可以运行微软的代码 简单代码如下 #include <stdio.h> #include &l…

uniapp 小程序获取WiFi列表

<template><view ><button click"getWifiList">获取WiFi列表</button><scroll-view:scroll-top"scrollTop"scroll-yclass"content-pop"><viewclass"itemInfo"v-for"(item, index) in wifiList&…

unity——Button组件单击双击长按功能

1.实现单击、双击、长按功能 using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; public class ButtonControl_Click_Press_Double : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler {publi…