vue 渲染 | 不同類型的元素渲染的方式(vue組件/htmlelement/純 html)

省流總結:(具體實現見下方)

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…