vue组件内外数据保持同步 组件数据加载解析顺序

news2024/11/17 17:44:40

背景与简介

一个公共的组件,比如BaseTable,需要同步组件内外部数据的同步,组件内部数据修改,组件外数据同步修改,组件外部数据修改,组件内部数据同步修改;同时,当组件内外部数据修改,需要执行某些数据的计算或赋值,比如动态计算树形表格的索引treeIndex。还要避免数据同步来回更新造成的死循环。

组件数据加载解析顺序

实例初始化完成、props 解析 -> beforeCreate -> 响应式数据、计算属性、方法和侦听器设置完成 -> created -> beforeMount -> mounted

  • 组件内外部使用push,$set,不修改原数组对象,会使得watch中的newValue等于oldValue,JSON.stringify(newValue) === JSON.stringify(oldValue)
  • watch加了immediate: true,先执行响应式数据初始化,立即触发watch后,走到created生命周期。
  • 没有immediate: true,的watch,触发时机是晚于created、mounted的,当数据再次发生变化后,beforeUpdate之前执行;
  • watch加了immediate: true,可以监听到响应式数据初始化后的变化。

组件内外执行顺序

1、加载渲染过程

父组件 beforeCreate -> created -> beforeMounted
子组件 beforeCreate -> created -> beforeMounted -> mounted
父组件 mounted

2、更新过程

父组件beforeUpdate
子组件beforeUpdate
子组件updated
父组件updated

3、销毁过程

父组件beforeDestory
子组件beforeDestory
子组件destoryed
父组件destoryed

代码实现

通过watch对组件内外部数据进行监听,实现数据同步

组件外状态数据 dataSource
组件内状态数据 list

@Watch('dataSource', { deep: true, immediate: true })
onDataSourceChange(newValue, oldValue) {
  console.log('%c ➡️ 张浩雨: onDataSourceChange -> newValue, oldValue ', 'font-size:16px;background-color:#ed9637;color:white;', newValue, oldValue, this.list)
  if (JSON.stringify(newValue) !== JSON.stringify(this.list)) { //* 组件外数据修改,内外数据不相同,组件内数据修改,内外数据相同
    //* 组件外数据不等于组件内的数据时,执行某些字段的额外操作
    this.baseConfig.showTree && this.setTreeIndex(newValue);
  }
  this.list = newValue; //* 组件外部数据同步到组件内的数据
  // this.listCopy = this.list;
}
@Watch('list', { deep: true })
onListChange(newValue, oldValue) {
  console.log('%c 🕘 张浩雨: onListChange -> newValue, oldValue ', 'font-size:16px;background-color:#cfa574;color:white;', newValue, oldValue)
  //todo 实时更新查询表单数据
  //* 始终执行某些字段的额外操作
  this.baseConfig.showTree && this.setTreeIndex(newValue);
  if (!newValue.length) this.selectedRecords = []; //* 展示“暂无数据”图片时,销毁了table组件,需要手动置空selectedRecords
  this.$emit('update:dataSource', newValue)
}

代码详解

1、组件内外数据,初始化时解析顺序

父组件 beforeCreate -> 响应式数据设置dataSource = [] -> created -> beforeMount
子组件 beforeCreate -> 响应式数据设置list = [],侦听器设置完成(dataSource的监听器immediate为true立即执行,监听到undefined 到 [] 的变化,运行代码this.list = this.dataSource,将组件外部数据同步到组件内的数据 ,没有immediate的不会立即执行)-> created -> beforeMount -> mounted
父组件 mounted

2、组件外部数据update

this.dataSource = [] -> dataSource的监听器监听到数据变更 -> 组件外数据不等于组件内的数据时,执行某些字段的额外操作,并且this.list = newValue,组件外部数据同步到组件内的数据 -> list的监听器监听到数据变更,this. e m i t ( ′ u p d a t e : d a t a S o u r c e ′ , n e w V a l u e ) ,将组件内部数据同步到组件外部,且不再触发 d a t a S o u r c e 的 w a t c h t h i s . d a t a S o u r c e = [ ] , emit('update:dataSource', newValue),将组件内部数据同步到组件外部,且不再触发dataSource的watch this.dataSource = [{}] , emit(update:dataSource,newValue),将组件内部数据同步到组件外部,且不再触发dataSourcewatchthis.dataSource=[]set、push -> 同上

3、组件内部数据update

变更之前,this.list === this.datasource //* true
this.list = [{}, {}] -> list的监听器监听到数据变更 -> 始终执行某些字段的额外操作,并this. e m i t ( ′ u p d a t e : d a t a S o u r c e ′ , n e w V a l u e ) ,将组件内部数据同步到组件外部 − > d a t a S o u r c e 的监听器监听到数据变更 − > 组件内数据修改,组件内外数据相同,无需执行某些字段的额外操作, t h i s . l i s t = n e w V a l u e ,切不会触发 l i s t 的 w a t c h t h i s . d a t a S o u r c e = [ ] , emit('update:dataSource', newValue),将组件内部数据同步到组件外部 -> dataSource的监听器监听到数据变更-> 组件内数据修改,组件内外数据相同,无需执行某些字段的额外操作,this.list = newValue,切不会触发 list的watch this.dataSource = [] , emit(update:dataSource,newValue),将组件内部数据同步到组件外部>dataSource的监听器监听到数据变更>组件内数据修改,组件内外数据相同,无需执行某些字段的额外操作,this.list=newValue,切不会触发listwatchthis.dataSource=[]set、push -> 同上

为什么始终执行某些字段的额外操作,不判断组件内外数据是否一致,或者不判断新老数据是否一致?
解释说明:

  1. 组件内部数据$set,push等修改原数据,新老数据一致
  2. 组件外部数据修改,this.list = this.dataSource,组件内外数据一致,所以始终都执行了某些字段的额外操作

参考vue3.0官网生命周期

vue生命周期时机详情
beforeCreate在组件实例初始化完成之后立即调用。会在实例初始化完成、props 解析之后、data() 和 computed 等选项处理之前立即调用。注意,组合式 API 中的 setup() 钩子会在所有选项式 API 钩子之前调用,beforeCreate() 也不例外。
created在组件实例处理完所有与状态相关的选项后调用。当这个钩子被调用时,以下内容已经设置完成:响应式数据、计算属性、方法和侦听器。然而,此时挂载阶段还未开始,因此 $el 属性仍不可用。
beforeMount在组件被挂载之前调用。当这个钩子被调用时,组件已经完成了其响应式状态的设置,但还没有创建 DOM 节点。它即将首次执行 DOM 渲染过程。
mounted在组件被挂载之后调用。组件在以下情况下被视为已挂载:所有同步子组件都已经被挂载。(不包含异步组件或 树内的组件)其自身的 DOM 树已经创建完成并插入了父容器中。注意仅当根容器在文档中时,才可以保证组件 DOM 树也在文档中。这个钩子通常用于执行需要访问组件所渲染的 DOM 树相关的副作用,或是在服务端渲染应用中用于确保 DOM 相关代码仅在客户端被调用。
beforeUpdate在组件即将因为一个响应式状态变更而更新其 DOM 树之前调用。这个钩子可以用来在 Vue 更新 DOM 之前访问 DOM 状态。在这个钩子中更改状态也是安全的。
updated在组件因为一个响应式状态变更而更新其 DOM 树之后调用。父组件的更新钩子将在其子组件的更新钩子之后调用。这个钩子会在组件的任意 DOM 更新后被调用,这些更新可能是由不同的状态变更导致的。如果你需要在某个特定的状态更改后访问更新后的 DOM,请使用 nextTick() 作为替代。不要在 updated 钩子中更改组件的状态,这可能会导致无限的更新循环!
beforeUnmount在一个组件实例被卸载之前调用。当这个钩子被调用时,组件实例依然还保有全部的功能。
unmounted在一个组件实例被卸载之后调用。一个组件在以下情况下被视为已卸载:其所有子组件都已经被卸载。所有相关的响应式作用 (渲染作用以及 setup() 时创建的计算属性和侦听器) 都已经停止。可以在这个钩子中手动清理一些副作用,例如计时器、DOM 事件监听器或者与服务器的连接。

vue2.0的官网解释

vue生命周期详情
beforeCreate在实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用。
created在实例创建完成后被立即同步调用。在这一步中,实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。然而,挂载阶段还没开始,且 $el property 目前尚不可用。
beforeMount在挂载开始之前被调用:相关的 render 函数首次被调用。该钩子在服务器端渲染期间不被调用。mounted: 实例被挂载后调用,这时 el 被新创建的 vm. e l 替换了。如果根实例挂载到了一个文档内的元素上,当 m o u n t e d 被调用时 v m . el 替换了。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm. el替换了。如果根实例挂载到了一个文档内的元素上,当mounted被调用时vm.el 也在文档内。注意 mounted 不会保证所有的子组件也都被挂载完成。如果你希望等到整个视图都渲染完毕再执行某些操作,可以在 mounted 内部使用 vm.$nextTick:该钩子在服务器端渲染期间不被调用。
beforeUpdate在数据发生改变后,DOM 被更新之前被调用。这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务器端进行。
updated在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。注意,updated 不会保证所有的子组件也都被重新渲染完毕。如果你希望等到整个视图都渲染完毕,可以在 updated 里使用 vm.$nextTick:该钩子在服务器端渲染期间不被调用。
beforeDestroy实例销毁之前调用。在这一步,实例仍然完全可用。该钩子在服务器端渲染期间不被调用。
destroyed实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。该钩子在服务器端渲染期间不被调用。
activated被 keep-alive 缓存的组件激活时调用。
deactivated被 keep-alive 缓存的组件失活时调用。

vue2.0官网图片

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java建筑工程建设智慧工地源码

智慧工地管理平台依托物联网、互联网,建立云端大数据管理平台,形成“端云大数据”的业务体系和新的管理模式,从施工现场源头抓起,最大程度的收集人员、安全、环境、材料等关键业务数据,打通从一线操作与远程监管的数据…

【Pytorch】学习记录分享13——OCR(Optical Character Recognition,光学字符识别)

[TOC](OCR(Optical Character Recognition,光学字符识别)) 1. OCR资源汇总 OCR(Optical Character Recognition,光学字符识别)指提取图像中的文字信息,通常包括文本检测和文本识别。 文字检测:将图片中的文字区域位置检测出来(如图1(b)所示…

FaceChain-FACT:免训练的丝滑体验,秒级别的人像生成

FaceChain-FACT:免训练的丝滑体验,秒级别的人像生成 项目主页:FaceChain-fact:Face Adapter for Human AIGC github项目:https://github.com/modelscope/facechain 1.介绍 作为AI人像写真开源项目的佼佼者&#xff…

华硕飞行堡垒FX53VD键盘全部失灵【除电源键】

华硕飞行堡垒FX53VD键盘全部失灵【除电源键】 前言一、故障排查二、发现问题三、使用方法总结 前言 版本型号: 型号 ASUS FX53VD(华硕-飞行堡垒) 板号:GL553VD 故障情况描述: 键盘无法使用,键盘除开机键外…

Qt During startup program exited with code 0xc0000135

网上试了好多办法没有用,可以试试在pro目录下加入如图所示的.dll 可以下个everything搜索整个电脑查看是否有上述dll,如果没有也可以网上下载或者点击连接

【博士每天一篇论文-算法】Optimal modularity and memory capacity of neural reservoirs

阅读时间:2023-11-15 1 介绍 年份:2019 作者:Nathaniel Rodriguez 印第安纳大学信息学、计算和工程学院,美国印第安纳州布卢明顿 期刊: Network Neuroscience 引用量:39 这篇论文主要研究了神经网络的模块…

认识SpringBoot中的条件注解

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringBoot ✨特色专栏&…

Java多线程并发篇----第四篇

系列文章目录 文章目录 系列文章目录前言一、volatile 是什么?可以保证有序性吗?二、Thread 类中的start() 和 run() 方法有什么区别?三、为什么wait, notify 和 notifyAll这些方法不在thread类里面?四、为什么wait和notify方法要在同步块中调用?前言 前些天发现了一个巨…

[足式机器人]Part3 机构运动学与动力学分析与建模 Ch00-2(4) 质量刚体的在坐标系下运动

本文仅供学习使用,总结很多本现有讲述运动学或动力学书籍后的总结,从矢量的角度进行分析,方法比较传统,但更易理解,并且现有的看似抽象方法,两者本质上并无不同。 2024年底本人学位论文发表后方可摘抄 若有…

MySQL 从零开始:04 增删改查

文章目录 1、准备工作2、insert 增加数据2.1 添加所有列的数据2.2 添加部分列2.3 一次插入多条数据 3、delete 删除记录4、update 更新记录5、select 查询记录5.1 查询所有行所有列5.2 查询指定行的所有列5.3 查询所有行的指定列5.4 查询指定行的指定列 在上一小节中介绍了 MyS…

狄克逊(Dixon)检验

目录 1.介绍:2.效果:小结: 1.介绍: 狄克逊检验法是一种用于检测异常值的统计方法,它是一种非参数的方法,可以有效地寻找数据集中不正常的观测值。该方法由美国统计学家布鲁斯E狄克逊(Bruce E. …

代理IP连接不上?网速过慢?自检与应对方法来了

当您使用代理时,您可能会遇到不同的代理错误代码显示代理IP连不通、访问失败、网速过慢等种种问题。 在本文中中,我们将讨论您在使用代理IP时可能遇到的常见错误、发生这些错误的原因以及解决方法。 一、常见代理服务器错误 当您尝试访问网站时&#…

【题解】—— LeetCode一周小结1

1.经营摩天轮的最大利润 题目链接: 1599. 经营摩天轮的最大利润 你正在经营一座摩天轮,该摩天轮共有 4 个座舱 ,每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮转座舱,但每次轮转都需要支付一定的运行成本 runningCost 。摩…

任务管理器的 top

文章目录 任务管理器的 top常规使用显示完整命令设置信息更新次数设置信息更新时间显示指定的进程信息指定用户的进程信息更多信息 任务管理器的 top top命令比较像Windows里面的任务管理器,提供一个动态实时的系统状态检测,可以检测实时显示内存、CPU、…

openGauss学习笔记-193 openGauss 数据库运维-常见故障定位案例-备机卡住-数据库只读

文章目录 openGauss学习笔记-193 openGauss 数据库运维-常见故障定位案例-备机卡住-数据库只读193.1 switchover操作时,主机降备卡住193.1.1 问题现象193.1.2 原因分析193.1.3 处理办法 193.2 磁盘空间达到阈值,数据库只读193.2.1 问题现象193.2.2 原因分…

不定期更新免费签|在线安装全能签轻松签万能签GBOX魔力签喵喵签|赶快白嫖

使用Safari浏览器打开 1.打开平台ios.hccld.com点击应用后的“获取”获取设备UDID,获取后在我的里上就会显示设备UDID信息。 2.点我的-购买证书,选择需要购买的证书进行购买。 3.点击“兑换证书”,输入购买的兑换码。 4.选择你要安装的签名安…

大模型PEFT技术原理(一):BitFit、Prefix Tuning、Prompt Tuning

随着预训练模型的参数越来越大,尤其是175B参数大小的GPT3发布以来,让很多中小公司和个人研究员对于大模型的全量微调望而却步,近年来研究者们提出了各种各样的参数高效迁移学习方法(Parameter-efficient Transfer Learning&#x…

论文封面表格制作

原文参考:【【论文排版】论文封面完美对齐 强迫症重度患者的经验分享】https://www.bilibili.com/video/BV18f4y1p7hc?vd_source046491acdcff4b39fed20406b36a93e2 视频里up主介绍很详细。我自己也记录一下。 介绍一下如何完成论文封面信息的填写。 创建一个3列…

「服务器」4.新手小白如何安装服务器环境-宝塔

刚开始初始化好的服务器,使用了阿里云客户端,看着网络脚本乱装,后来决定宝塔环境发现有重复的环境,遂决定重新初始化一下,然后重头干起。 重置服务器 将服务器关闭运行状态后,点击重新初始化云盘即可重新初…

【模拟IC学习笔记】 PSS和Pnoise仿真

目录 PSS Engine Beat frequency Number of harmonics Accuracy Defaults Run tranisent?的3种设置 Pnoise type noise Timeaverage sampled(jitter) Edge Crossing Edge Delay Sampled Phase sample Ratio 离散时间网络(开关电容电路)的噪声仿真方法 PSS PSS…