44 el-dialog 的 appendToBody 属性, 导致 vue 响应式失效

news/2024/4/29 5:59:50/文章来源:https://blog.csdn.net/u011039332/article/details/135612296

前言

我们经常会碰到 一些 模型和视图 不同步的问题 

通常意义上 主要的问题为 列表的某响应式数据更新着更新着 后面就变成非响应式对象了, 然后 就造成了 数据一直在更新, 但是 视图的渲染后面就未渲染了, 这是一个由于 模型上的问题 导致的数据的不在响应式更新

又或者 是因为使用了相关 vue 未能够检测到的 api 来更新 对象, 数组 的元素, 然后导致的数据的不同步, 数据更新了 但是视图未更新

然后 我们这里来看一下 另外的一个 由于vue这边视图更新造成的一个数据 不同步的情况, 这里的情况是 模型里面增加了一条数据, 但是 页面上 没有渲染出来

这个问题 还是很有意思, 是和 vue 这边渲染视图元素有一些关系 

核心比较关键的元素是 el-dialog, 然后其中有一个 appendToBody 的属性

 

 

vue 模型视图不同步同类型题材的文章可以参见 

el-tree defaultCheckedKeys配置 和 树上面选中节点不同步问题

特定的操作之后响应式对象不“响应“了(一)

特定的操作之后响应式对象不“响应“了(二)

直接使用 dom api 更新了 #text节点, 之后响应式更新不生效了

 

 

测试用例

<template><div class="testParent"><div v-for="dayPlan in weekPlan" style="display: flex;" ><el-tag type="warning">{{dayPlan.name}}</el-tag><div class="block" v-for="biz in dayPlan.children" style="display: inline; float:left;"><el-tag type="warning">{{biz.time}}</el-tag><el-input v-model="biz.biz" :name="biz.biz" ></el-input></div><el-dialog :visible.sync="visible" v-if="dialogVisible" width="480px" :show-close="true" :modal="false":append-to-body="true" ><span>是否退出登录?</span></el-dialog></div><el-button style="position: absolute; top: 100px; left : 1500px; " @click="handleClick" > click </el-button></div></template><script>export default {name: "HelloElInputUpdate",data() {return {visible: false,dialogVisible: true,weekPlan: [{id: "01", name: "monday",children: [{time: "morning",biz: "chinese"}, {time: "afternoon",biz: "english"}]},{id: "02", name: "tuesday",children: [{time: "morning",biz: "math"}, {time: "afternoon",biz: "english"}]},{id: "03", name: "wednesday",children: [{time: "morning",biz: "math"}, {time: "afternoon",biz: "english"}]}],}},computed: {},mounted() {let _this = thissetTimeout(function() {_this.weekPlan[2].children[0].biz = "updated"console.log(" updated ")}, 5000)setTimeout(function() {_this.weekPlan[1].children.push({time: "night", biz: "tv"})console.log(" newly created ")}, 6000)},created() {},methods: {handleClick() {this.visible = !this.visible}},}
</script><style></style>

 

 

正常情况 

如果是 不点击 click 按钮来操作 对话框相关

可以看到 mounted 之后的两个操作是正常的, 最终 tuesday 可以看到增加的晚上的计划, wednesday morning 的事项发生了改变 

b4aae80dc4144f01a13d592506f8ad89.png

 

 

异常情况

此时 就需要我们 在 mounted 的操作之前, 点击 click 按钮了 

然后 我们看一下 情况是怎么样的? 

可以看到 wednesday morning 的事项发生了改变, 但是 tuesday 增加的晚上的计划 在页面是没有展示出来的

272846f7ecbf412e957b38da52c43d46.png

 

首先我们通过 click 按钮, 来看一下 整个数据模型的情况

可以看到 在数据模型上面, 是正确的,  tuesday 增加的晚上的计划 是已经在添加进去了 

b5df9d47fffd42e681700bd7f0c415c1.png

 

我们再看一下 页面元素渲染的地方

这里可以看到 vue 这边根据页面元素渲染 vnode 的时候也是正确的, 可以正确拿到 tuesday 的三个计划 

21e11c063feb4826947fd94fe1ec493d.png

 

这里的 patchVNode 是一层一层的再比较 

然后 这里可以通过上下文 parentElm, oldCh, newCh 可以判断出当前是在比较 tuestday 中的改动前后的元素 

截图 newCh 总共有五个元素, 一个是 el-tag, 中间三个为 tuesday 的 三个工作计划, 最后一个为 对话框的元素

然后这里 和 oldCh 对比, oldCh 只有四个元素, 一个是 el-tag, 中间两个为 tuesday 的 三个工作计划, 最后一个为 对话框的元素

然后比较 oldCh, newCh 的差异是需要在 oldCh 的第二个工作计划之后再增加一个工作计划 : {time: "night", biz: "tv"

然后 后面会 根据 vnode 渲染时间的 dom 元素, 然后 添加到页面中

c966c44decd24ecb9ebf35477398723a.png

 

这里会创建 工作计划 : {time: "night", biz: "tv"} 的父级 div 元素, 以及子级的 el-tag 和 el-input, 这个具体的细节 我们先暂时不管, 可以理解为我们这里 vnode.elm 即为创建好的 dom 元素 

然后 另外一个比较关键的元素是 refElem, 是一个参照元素, 标记了目标新增元素 应该放在那里

46ee4e33c8ed435983a3cebb2a7f2228.png

 

在我们这里的场景新增的 工作计划 : {time: "night", biz: "tv"} 按道理其之后应该是 对话框节点, 所以所这里计算的 refElm 即为对话框对应的节点 

但是 这个节点因为我们前面配置了 appendToBody 的配置, 这个节点被移动出去了, 在dom层级上已经没有这个节点了, 甚至连它的 comment 节点也没有了 

62d6c8fd05bd44f88a404f82d96638ac.png

 

vue 更新页面元素的时候, 数据的 dom 结构如下 

可以看到在 monday, tuesday, wednesday 的数据节点下面是没有只有 el-tag, 两个工作节点, 没有 vnode模型上面的 dialog 节点 

然后 dialog 节点是在 外层的 body 下面 

fbacb14ba0864d96acb2546aea768319.png

 

然后这里添加 dom 节点的时候, 发现 ref节点 甚至不在 parent 下面, 然后 直接跳过了 dom 元素的添加 

因此 最终页面上 看不到这个本应该渲染的 工作节点

ca13a41a6425407d8d3e1bd7f32d147e.png

 

引起这里的问题, 主要的原因是 dom 结构变化了, 但是 vnode 的结构却没有发生变化 

进而导致 vue 这边根据 vnode 的结构渲染新的元素的时候, 出现异常 

解决的方式, 不要将 dialog 放置于可能新增元素的节点 后面, 另外用例中 将 dialog 放置于循环中 本来也是一个问题

 

 

如果 appendToBody 配置为 false 会怎么样?

点击了 dialog 之后, 可以看到对应的 wrapper 的 div 依然还是在原来的 dom 层级上面 

然后 vue 这时候基于 dialog节点 来添加元素, 可以正常添加到 

6c18d2befe5840fcb36a221d2ed92025.png

 

添加目标工作节点的时候

ddb5fc9b07a049789ad6fff439086e42.png

 

 

 

 

 

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

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

相关文章

Luminar Neo:重塑图像编辑新纪元,Mac与Win双平台畅享创意之旅

在数字时代的浪潮中&#xff0c;图像编辑软件已成为摄影师和设计师们不可或缺的创作工具。Luminar Neo&#xff0c;作为一款专为Mac与Windows双平台打造的图像编辑软件&#xff0c;正以其卓越的性能和创新的编辑功能&#xff0c;引领着图像编辑的新潮流。 Luminar Neo不仅继承…

Docker新手攻略:编辑Dockerfile、构建镜像、启动容器全攻略

万能dockerfile编写模板文件 FROM openjdk:11.0 as builder WORKDIR application ARG JAR_FILEtarget/*.jar COPY ${JAR_FILE} application.jar RUN java -Djarmodelayertools -jar application.jar extractFROM openjdk:11.0 WORKDIR application COPY --frombuilder applica…

小狐狸JSON-RPC:钱包连接,断开连接,监听地址改变

detect-metamask 创建连接&#xff0c;并监听钱包切换 一、连接钱包&#xff0c;切换地址&#xff08;监听地址切换&#xff09;&#xff0c;断开连接 使用npm安装 metamask/detect-provider在您的项目目录中&#xff1a; npm i metamask/detect-providerimport detectEthereu…

算法---动态规划练习-6(地下城游戏)

地下城游戏 1. 题目解析2. 讲解算法原理3. 编写代码 1. 题目解析 题目地址&#xff1a;点这里 2. 讲解算法原理 首先&#xff0c;定义一个二维数组 dp&#xff0c;其中 dp[i][j] 表示从位置 (i, j) 开始到达终点时的最低健康点数。 初始化数组 dp 的边界条件&#xff1a; 对…

后端常问面经之Spring和Mybatis框架

Spring的IOC介绍一下&#xff1a; 所谓控制就是对象的创建、初始化、销毁。 创建对象&#xff1a;原来是 new 一个&#xff0c;现在是由 Spring 容器创建。 初始化对象&#xff1a;原来是对象自己通过构造器或者 setter 方法给依赖的对象赋值&#xff0c;现在是由 Spring 容器…

课堂练习:环境体验——3、Linux 权限管理

任务描述 本关任务&#xff1a;根据所学知识&#xff0c;完成文件权限的修改。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 如何创建和删除用户以及用户的权限管理&#xff1b;如何设置文件的访问权限。 Linux的权限管理主要分为两类&#xff1a;用户和…

人脸情绪识别(1)附代码

1.目标 实现人脸情绪实时检测&#xff0c;通过摄像头拍摄人脸并显示出相应情感类别。 代码地址&#xff1a; 2.Emotion-Detection-RealTime 2.1 目录结构 2.2 代码结构 模块导入 参数设置 数据处理 模型构建 训练脚本 展示脚本 2.3 具体代码 import numpy as np import arg…

JAVA的NIO和BIO底层原理分析

文章目录 一、操作系统底层IO原理1. 简介2. 操作系统进行IO的流程 二、BIO底层原理1. 什么是Socket2. JDK原生编程的BIO 三、Java原生编程的NIO1. 简介2. NIO和BIO的主要区别3. Reactor模式4. NIO的三大核心组件5. NIO核心源码分析 一、操作系统底层IO原理 1. 简介 IO&#x…

马斯克旗下xAI发布Grok-1.5,相比较开源的Grok-1,各项性能大幅提升,接近GPT-4!

本文原文来自DataLearnerAI官方网站&#xff1a;马斯克旗下xAI发布Grok-1.5&#xff0c;相比较开源的Grok-1&#xff0c;各项性能大幅提升&#xff0c;接近GPT-4&#xff01; | 数据学习者官方网站(Datalearner) 继Grok-1开源之后&#xff0c;xAI宣布了Grok-1.5的内测消息&…

qt学习第三天,qt设计师的第一个简单案例

3月25&#xff0c;应用qt设计师&#xff0c;手动设计界面形状 ​ 如何启动qt设计师&#xff0c;找到对应的安装地点&#xff0c;对应你自己安装的pyside6或其他qt的安装路径来找 ​ 应用qt设计师的优点是不用敲代码然后慢慢调节框框大小&#xff0c;位置等、可以直接修改…

武汉星起航:亚马逊物流创新,塑造未来零售的新篇章

亚马逊&#xff0c;作为全球电商的领军者&#xff0c;不仅在商品销售方面取得了举世瞩目的成就&#xff0c;更在物流领域进行了一系列颠覆性的创新。武汉星起航了解到这些创新不仅提升了消费者的购物体验&#xff0c;也为整个物流行业树立了新的标杆。 亚马逊在物流技术方面的…

201基于matlab的成绩管理系统

基于matlab的成绩管理系统。自带的GUI界面设计了一个成绩管理界面&#xff0c;可进行成绩的载入、查询、绘图、求平均分。可更改自己的数据进行录入。包含作业文档。程序已调通&#xff0c;可直接运行。 201 matlab 成绩管理系统 GUI - 小红书 (xiaohongshu.com)

“数据持久化”和“缓存与数据库不一致”到底有什么区别?

之前&#xff0c;我一直把“数据持久化”和“缓存与数据库不一致问题”给搞混了。我当时复习的时候基本上就没有思考&#xff0c;就是纯背诵&#xff0c;数据持久化是什么&#xff0c;数据持久化有两种方式&#xff0c;这两种方式特点是什么&#xff0c;然后巴拉巴拉一堆。缓存…

k8s入门到实战(三)—— 三台服务器从零开始搭建k8s集群

服务器裸机搭建 k8s 集群 环境准备 至少3个服务器&#xff08;本次使用3台阿里云服务器&#xff09;&#xff0c;4核4G以上&#xff08;按量付费&#xff09;&#xff0c;内网要能互相通信&#xff0c;也就是必须要在同一个网段下 本次实验的3个服务器私网 ip 如下&#xff…

【数据结构 | 图论】如何用链式前向星存图(保姆级教程,详细图解+完整代码)

一、概述 链式前向星是一种用于存储图的数据结构&#xff0c;特别适合于存储稀疏图&#xff0c;它可以有效地存储图的边和节点信息&#xff0c;以及边的权重。 它的主要思想是将每个节点的所有出边存储在一起&#xff0c;通过数组的方式连接&#xff08;类似静态数组实现链表…

海外媒体发稿:10种提升出口贸易媒体发稿推广的方法-华媒舍

出口贸易对于一个国家的经济发展至关重要。而有效的媒体发稿推广是扩大出口贸易的关键。本篇科普介绍文章将为大家介绍10种提升出口贸易媒体发稿推广效果的秘笈。 1. 独特而吸引人的标题 一个独特而吸引人的标题是吸引媒体和读者关注的第一步。确保标题简洁、具有吸引力&#…

实战 | 微调训练TrOCR识别弯曲文本

导 读 本文主要介绍如何通过微调训练TrOCR实现弯曲文本识别。 背景介绍 TrOCR&#xff08;基于 Transformer 的光学字符识别&#xff09;模型是性能最佳的 OCR 模型之一。在我们之前的文章中&#xff0c;我们分析了它们在单行打印和手写文本上的表现。 TrOCR—基于Transforme…

微信小程序实战:无痛集成腾讯地图服务

在移动互联网时代,地图服务无疑是应用程序中最常见也最实用的功能之一。无论是导航定位、附近搜索还是路线规划,地图服务都能为用户提供极大的便利。在微信小程序开发中,我们可以轻松集成腾讯地图服务,为小程序赋能增值体验。本文将详细介绍如何在微信小程序中集成使用腾讯地图…

Uos中Qt Creator中无法显示qDebug()相关信息

[TOC](Uos中Qt Creator中无法显示qDebug()相关信息) 一、概述 操作系统&#xff1a;统信 UOS 20.1070 在Uos系统中&#xff0c;我在Qt Creator中写了 qDebug()等代码&#xff0c;但是在 应用程序 输出中无法看到对应的调试输出&#xff0c;但是使用的 std::cout 等输出功能无…

查询优化-提升子查询-UNION类型

瀚高数据库 目录 文档用途 详细信息 文档用途 剖析UNION类型子查询提升的条件和过程 详细信息 注&#xff1a;图片较大&#xff0c;可在浏览器新标签页打开。 SQL: SELECT * FROM score sc, LATERAL(SELECT * FROM student WHERE sno 1 UNION ALL SELECT * FROM student…