省流总结:(具体实现见下方)

vue 组件 ——》<component :is='组件名'> 

htmlelement 元素 ——》 ref 、★ v-for + ref 或是  vue 的 nextTick

纯 html 结构——》v-html 

另外,当数据异步加载时,vue3中如何渲染:①watch监听;②异步加载+条件渲染;③ watch(监听对象, async(newValue)=>{... await nextTick() }


vue 组件的 动态渲染 ——》 <component :is="组件名"

<component :is="componentName"></component>

是 Vue 中的动态组件用法,它允许你根据某个条件动态地渲染不同的组件

不适合原生的 DOM 元素。

其中,

:is  指令 让你能够指定要渲染的组件类型

componentName 是一个字符串,表示你要渲染的组件的名称,或者是一个组件对象。可以是本地注册的组件名称,或者一个导入的组件对象。

 例子:

<template><div><button @click="setComponent('componentA')">Show Component A</button><button @click="setComponent('componentB')">Show Component B</button><!-- 动态渲染组件 --><component :is="currentComponent"></component></div>
</template><script>
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';export default {data() {return {currentComponent: 'ComponentA',  // 初始渲染ComponentA};},methods: {setComponent(componentName) {this.currentComponent = componentName;},},components: {ComponentA,ComponentB,},
};
</script>

在这个例子中,<component :is="currentComponent"> 会根据 currentComponent 的值动态切换 ComponentAComponentB。 


htmlelement 元素——》 ref  渲染

HTMLElement 通过 ref 引用传递给 Vue,直接操作 DOM 结构,HTMLElement 添加到某个元素中。适用于需要直接操作 DOM 的情况(更灵活)。

例子:

<template><div ref="container"></div> <!-- 渲染到指定的 DOM 元素 -->
</template><script>
import { store } from './store';export default {mounted() {this.renderElement();},methods: {renderElement() {const container = this.$refs.container;const element = store.state.component;if (container && element) {container.appendChild(element);  // 将 HTMLElement 添加到指定的 ref 元素中}},},
};
</script>

使用 v-for + ref 渲染 HtmlElement 元素

实现:渲染component属性,canvasItems数组中,每个对象中都有一个component属性(即 htmlElement 元素)

vue2版本:

// store.js
export const store = {state: {canvasItems: [{id: 1,component: document.createElement('div'), // 假设这是 HTML 元素type: 'image',properties: { /* 其他属性 */ }},{id: 2,component: document.createElement('button'), // 另一个 HTML 元素type: 'button',properties: { /* 其他属性 */ }}]}
};

 vue 组件中,通过 v-for 渲染每个 component:

<template><div><!-- 遍历 canvasItems 渲染每个 component --><div v-for="(item, index) in canvasItems" :key="item.id"><!-- 渲染对应的 HTMLElement --><div :ref="`container-${index}`"></div></div></div>
</template><script>
import { store } from './store';export default {computed: {canvasItems() {return store.state.canvasItems; // 获取 store 中的 canvasItems 数据}},mounted() {this.renderCanvasItems();},methods: {renderCanvasItems() {// 遍历 canvasItems 并渲染每个 HTMLElementthis.canvasItems.forEach((item, index) => {const container = this.$refs[`container-${index}`]; // 获取每个 item 对应的 refif (container && item.component) {container.appendChild(item.component); // 将 HTMLElement 插入到指定位置}});}}
};
</script>
代码解释:
  1. v-for 遍历:我们使用 v-for 循环遍历 canvasItems 数组中的每个元素。

  2. ref 动态绑定ref 的值通过 模板字符串 \container-${index}` 来动态生成不同的 ref` 名称,以便在方法中获取每个对应的容器。

  3. appendChild 插入 DOM:在 mounted 钩子中,我们通过 this.$refs 获取到每个容器,并将 component(即 HTMLElement插入到对应的容器中。

注:vue3 语法糖中,可以把 this.$refs  换成  const xxx = ref() 


vue3 <script setup> 语法糖版本:

<template><div><div v-for="(item, index) in items" :key="item.id"><!-- 使用函数形式的 ref --><div :ref="(el) => setContainerRef(el, index)"></div></div></div>
</template><script setup>
import { ref, onMounted } from 'vue'
import { canvasItems } from './store'// 存储 DOM 引用的容器
const containerRefs = ref([])
const items = ref(canvasItems.value || []);      // 若 canvansItems 是响应式引用Ref,则可以不加这一步。// 设置引用的函数
const setContainerRef = (el, index) => {if (el) {containerRefs.value[index] = el}
}onMounted(() => {// 确保 canvasItems 已正确赋值if (canvasItems.value) {// 遍历 canvasItems 数组并访问每个 item 的 component 属性canvasItems.value.forEach((item, index) => {const container = containerRefs.value[index]if (container && item.component) {container.appendChild(item.component) // 将 HTMLElement 插入到指定容器}})} else {console.error('canvasItems is not defined or empty')}
})
</script>

关键变化说明:

  1. 移除了 this 的使用,改用 响应式变量

  2. 使用 :ref="(el) => setContainerRef(el, index)" 替代字符串形式的 ref 

  3. 使用 containerRefs 数组 来存储 DOM 引用

  4. 将 mounted 生命周期钩子改为 onMounted

  5. 移除了 computed 属性,直接在 setup 中声明响应式变量


★ vue3 <script setup> 进阶版本: 数据是异步加载的。(onMounted 挂载时 数据还没有准备好)

法1:使用 watch 监听 数据变化——》watch(监听对象(newValue)=>{响应} {deep:true 开启深度监听})
<script setup>
import { ref, watch, onMounted } from 'vue'
import { canvasItems } from './store'const containerRefs = ref([])
const isMounted = ref(false)const setContainerRef = (el, index) => {if (el) containerRefs.value[index] = el
}// 监听 canvasItems 变化
watch(canvasItems, (newItems) => {if (!newItems || !isMounted.value) returnnewItems.forEach((item, index) => {const container = containerRefs.value[index]if (container && item.component) {container.appendChild(item.component)}})
}, { deep: true })onMounted(() => {isMounted.value = true// 如果数据已经加载,立即执行if (canvasItems.value) {canvasItems.value.forEach((item, index) => {const container = containerRefs.value[index]if (container && item.component) {container.appendChild(item.component)}})}
})
</script>
法2:使用 异步加载 + 条件渲染 ——》async ... await new Promise( res=>{})  + nextTick()
<template><div v-if="loaded"><div v-for="(item, index) in items" :key="item.id"><div :ref="(el) => setContainerRef(el, index)"></div></div></div><div v-else>Loading...</div>
</template><script setup>
import { ref, onMounted } from 'vue'
import { canvasItems } from './store'const containerRefs = ref([])
const loaded = ref(false)
const items = ref([])const setContainerRef = (el, index) => {if (el) containerRefs.value[index] = el
}// 假设有一个异步加载函数
const loadData = async () => {// 这里可能是从API加载数据await new Promise(resolve => setTimeout(resolve, 500)) // 模拟异步items.value = canvasItems.value || []loaded.value = truenextTick(() => {items.value.forEach((item, index) => {const container = containerRefs.value[index]if (container && item.component) {container.appendChild(item.component)}})})
}onMounted(loadData)
</script>
 法3:使用 nextTick 确保DOM更新 ——》 watch(监听对象,async(newValue)=>{... await nextTick() //等待 DOM 更新}) 
<script setup>
import { ref, watch, nextTick } from 'vue'
import { canvasItems } from './store'const containerRefs = ref([])const setContainerRef = (el, index) => {if (el) containerRefs.value[index] = el
}watch(canvasItems, async (newItems) => {if (!newItems) returnawait nextTick() // 等待DOM更新newItems.forEach((item, index) => {const container = containerRefs.value[index]if (container && item.component) {container.appendChild(item.component)}})
}, { immediate: true, deep: true })
</script>
 注: await nextTick() // 等待DOM更新

最佳实践建议:

  1. 如果数据来自API,使用方案2的 异步加载模式

  2. 如果数据来自 store且可能动态变化,使用方案1或方案3

  3. 确保在操作DOM前使用 nextTick 等待DOM更新完成

根据你的具体场景选择最适合的方案。如果是画布应用,通常方案1的watch方式最为可靠。


应用 - 具体实践:


DOM元素 ——》用 onMounted  钩子 手动直接操作 DOM

如果你需要 Vue 渲染完成后 动态插入 DOM 元素,可以考虑使 mounted 钩子来手动操作 DOM:

<template><div><!-- 渲染容器 --><div v-for="(item, index) in canvasItems" :key="item.id" :ref="'container-' + index"></div></div>
</template><script>
import { store } from './store';export default {computed: {canvasItems() {return store.state.canvasItems;}},mounted() {this.renderCanvasItems();},methods: {renderCanvasItems() {this.canvasItems.forEach((item, index) => {const container = this.$refs[`container-${index}`];if (container && item.component) {container.appendChild(item.component); // 将 HTMLElement 插入到 DOM 中}});}}
};
</script>

纯 HTML 字符串——》 v-html  指令 渲染  outerHTML

通过 v-html 指令, HTMLElement 转换为 HTML 字符串 后插入到页面。请注意,v-html 仅适用于 纯 HTML 字符串 的渲染,并不会解析 Vue 组件或 HTMLElement

function getHtmlContent(element) {console.log('getHtmlContent==========element=', element);return element ? element.outerHTML : ''; // 将 HTMLElement 转换为字符串
}

 然,在模板中使用 v-html 

<div v-for="item in canvasItems"  v-html="getHtmlContent(item. Component)" :key="item.id" ></div>

参考:vue3 | Vue2代码转换成Vue3_vue2转vue3-CSDN博客

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

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

相关文章

Charles中文版深度解析,轻松调试API与优化网络请求

在现代软件开发过程中&#xff0c;调试API、捕获HTTP/HTTPS流量以及优化网络性能是开发者不可避免的挑战。特别是在处理复杂的网络请求和验证API接口的数据传输准确性时&#xff0c;开发者需要一款强大且易于使用的工具。Charles抓包工具凭借其功能强大、界面简洁、易于操作的特…

【CF】Codeforces Round 1039 (Div. 2) E1 (二分答案求中位数)

E1. Submedians (Easy Version)题目&#xff1a;思路&#xff1a;经典不过加了点东西对于求中位数&#xff0c;我们必然要想到二分答案&#xff0c;具体的&#xff0c;对于所有大于等于 x 的数我们令其奉献为 1&#xff0c;小于的为 -1&#xff0c;如果存在某段区间的奉献和大于…

ESP32-S3学习笔记<8>:LEDC的应用

ESP32-S3学习笔记&#xff1c;8&#xff1e;&#xff1a;LEDC的应用1. 头文件包含2. LEDC的配置2.1 配置定时器2.1.1 speed_mode/设置速度模式2.1.2 duty_resolution/设置占空比分辨率2.1.3 timer_num/选择定时器2.1.4 freq_hz/设定PWM频率2.1.5 clk_cfg/选择LEDC的外设时钟源2…

网络安全第14集

前言&#xff1a;小迪安全14集&#xff0c;这集重点内容&#xff1a;0、什么是js渗透测试&#xff1f;在javascript中也存在变量和函数&#xff0c;存在可控变量和函数就有可能存在在漏洞&#xff0c;js开发的web应用和php、java开发的区别是&#xff0c;js能看得到的源代码&am…

代码随想录算法训练营第三十三天

LeetCode.62 不同路径 题目链接 不同路径 题解 class Solution {public int uniquePaths(int m, int n) {// dp表示到达ij有多少条路径int[][] dp new int[110][110];dp[1][1] 1;for(int i 0;i<m;i){dp[i][0] 1;}for(int j 0;j<n;j){dp[0][j] 1;}for(int i 1;i…

银行回单OCR识别技术原理

银行回单OCR&#xff08;光学字符识别&#xff09;技术通过结合图像处理、模式识别和自然语言处理&#xff08;NLP&#xff09;技术&#xff0c;将纸质或电子版银行回单中的非结构化文本&#xff08;如账号、金额、日期等&#xff09;转化为结构化数据。以下是其核心原理和关键…

Day22-二叉树的迭代遍历

昨天学习了递归遍历&#xff1a;递归就是一次次的把参数压入栈中&#xff0c;然后返回的时候还是上一次递归保存的参数。今天学习迭代遍历。迭代遍历就是用栈去模拟保存二叉树的节点&#xff0c;然后依次去遍历&#xff0c;只不过要注意栈的后入先出的规则。前序遍历&#xff1…

知识蒸馏 - 通过引入温度参数T调整 Softmax 的输出

知识蒸馏 - 通过引入温度参数T调整 Softmax 的输出 flyfish import torch import torch.nn.functional as F import matplotlib.pyplot as plt import numpy as np# 设置中文字体支持 plt.rcParams["font.family"] [AR PL UMing CN] # Linux plt.rcParams[axes.uni…

Java研学-RabbitMQ(三)

一 消息通信协议 1 AMQP AMQP 是一个开放的、跨语言、跨平台的消息协议标准&#xff0c;用于在分布式系统中传递业务消息。它定义了消息队列的二进制协议格式和交互模型&#xff08;如交换机、队列、绑定等&#xff09;&#xff0c;确保不同语言&#xff08;Java、Python、C#等…

http.client 教程-如何使用 Python 标准库发送 HTTP 请求

http.client 教程-如何使用 Python 标准库发送 HTTP 请求以下是 http.client 模块的详细使用教程&#xff0c;帮助你理解如何使用 Python 标准库发送 HTTP 请求&#xff1a;1. http.client 概述http.client 是 Python 内置的 HTTP 客户端库&#xff0c;提供了底层的 HTTP 协议实…

Android-三种持久化方式详解

持久化技术分为3种&#xff0c;文件&#xff0c;sharedPreferences存储&#xff0c;数据库来存储&#xff1b; 目录 文件存储&#xff1a; 利用SharedPreferences中读取数据 SQLite创建数据库 更新 添加 删除 查找&#xff1a; 文件存储&#xff1a; 文件存储是 Andr…

并发安全之锁机制一

锁机制一 锁机制是计算机系统中解决并发冲突的核心工具&#xff0c;其存在和应用场景源于一个根本问题&#xff1a;当多个执行单元&#xff08;线程、进程、分布式节点&#xff09;同时访问或修改同一份共享资源时&#xff0c;如何保证数据的正确性、一致性和系统可靠性&#x…

结合项目阐述 设计模式:单例、工厂、观察者、代理

原文链接&#xff1a;https://download.csdn.net/blog/column/12433305/133862792#_1613 1、工厂模式应用 C17及之后可编译 /*日志落地模块的实现1.抽象落地基类2.派生子类&#xff08;根据不同落地方向进行派生&#xff09;3.使用工厂模式进行创建与表示的分离 */#ifndef _…

uniapp 更新apk有缓存点不动,卸载安装apk没有问题。android

方式一。pages.json&#xff1a;"globalStyle" : {"navigationBarTextStyle" : "black","navigationBarTitleText" : "uni-app","navigationBarBackgroundColor" : "#F8F8F8","backgroundColor&qu…

HTML响应式SEO公司网站源码

核心优势 100%纯HTML/CSS开发自动适配手机/平板/PC内置SEO优化结构0.5秒极速加载 包含页面 • 首页&#xff08;关键词布局优化版&#xff09; • 服务项目展示页 • 客户案例库 • 新闻资讯系统 • 联系方式&#xff08;带地图API&#xff09; 技术参数 兼容Chrome/Firefo…

Error: llama runner process has terminated: exit status 2

我是i7 12700h ,3080显卡&#xff0c;在 Windows 11 上运行 ollama run deepseek-r1:1.5b 出现 Error: llama runner process has terminated: exit status 2 之前是好用的&#xff0c;后来不知为什么就不好用了。 原因&#xff1a; 检查 Microsoft Visual C Redistributab…

Linux中ssh远程登录原理与配置

SSH连接的五个阶段 1. 版本协商阶段&#xff08;Protocol Version Negotiation&#xff09;目的&#xff1a;协商使用SSH-1或SSH-2协议&#xff08;现代系统默认SSH-2&#xff09;。流程&#xff1a;关键点&#xff1a;若版本不兼容&#xff08;如客户端只支持SSH-1&#xff0c…

Kubernetes --存储入门

一、Volume 的概念对于大多数的项目而言&#xff0c;数据文件的存储是非常常见的需求&#xff0c;比如存储用户上传的头像、文件以及数据库的数据。在 Kubernetes 中&#xff0c;由于应用的部署具有高度的可扩展性和编排能力&#xff08;不像传统架构部署在固定的位置&#xff…

蚂蚁 KAG 框架开源:知识图谱 + RAG 双引擎

引言&#xff1a;从RAG到KAG&#xff0c;专业领域知识服务的技术突破 在大语言模型&#xff08;LLM&#xff09;应用落地过程中&#xff0c;检索增强生成&#xff08;RAG&#xff09; 技术通过引入外部知识库有效缓解了模型幻觉问题&#xff0c;但在专业领域仍面临三大核心挑战…

V-Ray 7.00.08 for 3ds Max 2021-2026 安装与配置教程(含语言补丁)

本文介绍 V-Ray 7.00.08 渲染器在 3ds Max 2021-2026 各版本中的安装与使用配置步骤&#xff0c;适合需要进行可视化渲染工作的设计师、建筑师及相关从业者。附带语言补丁配置方式&#xff0c;帮助用户获得更顺畅的使用体验。 &#x1f4c1; 一、安装文件准备 软件名称&#xf…