vue中根據html動態渲染內容

需求:根據數據中的html,因為我是在做填空,所以是需要將html中的_____替換成input,由于具體需求我使用的是元素contenteditable代替的可編輯的input

html部分

<div class="wrap"><component :is="renderedContent" ref="wrap_component" /></div>

js部分

// 這個是為了保證輸入的時候光標保持在最后
const moveCursorToEnd = (element: HTMLElement) => {const range = document.createRange();const selection = window.getSelection();// 找到最后一個文本節點let lastTextNode: Text | any = null;const traverseNodes = (node: Node) => {if (node.nodeType === Node.TEXT_NODE) {lastTextNode = node as Text;}for (let i = 0; i < node.childNodes.length; i++) {traverseNodes(node.childNodes[i]);}};traverseNodes(element);if (lastTextNode) {range.setStart(lastTextNode, lastTextNode.textContent?.length || 0);range.collapse(true);if (selection) {selection.removeAllRanges();selection.addRange(range);}} else {range.setStart(element, 0);range.collapse(true);if (selection) {selection.removeAllRanges();selection.addRange(range);}}// 兼容性處理:確保元素獲取焦點element.focus();if (document.activeElement !== element) {element.focus();}
};// 計算屬性,用于生成渲染內容
const renderedContent = computed(() => {if (!itemConf.value.customConf?.inputHtml) return null;const parts = itemConf.value.customConf.inputHtml.split(/_{1,}/);let nodes: any = [];parts.forEach((part, index) => {if (part) {const replacedSpaces = part.replace(/ /g, '&nbsp;');const replacedPart = replacedSpaces.replace(/<div>/g, '<br>').replace(/<\/div>/g, '');nodes.push(h('span', { class: 'custom-span', innerHTML: replacedPart }));}if (index < parts.length - 1) {if (!inputValues.value[index]) {inputValues.value[index] = '';}if (!isInputFocused.value[index]) {isInputFocused.value[index] = false;}if (!isClearIconClicked.value[index]) {isClearIconClicked.value[index] = false;}if (!clearIconHideTimer.value[index]) {clearIconHideTimer.value[index] = 0;}const clearIcon = h(ElIcon,{class: ['clear_icon',{'is-hidden':inputValues.value[index].length === 0 ||itemConf.value.baseConf.isReadOnly ||!isInputFocused.value[index],},],onClick: () => {if (!itemConf.value.baseConf.isReadOnly) {isClearIconClicked.value[index] = true;inputValues.value[index] = '';if (inputRefs.value[index]) {inputRefs.value[index].innerText = '';}adjustInputWidth(index);handleChange(itemConf.value.customConf.inputGroup[index], '');// 點擊后清除隱藏定時器clearTimeout(clearIconHideTimer.value[index]);}},},{ default: () => h(CircleClose) },);const inputNode = h('p',{contenteditable: !itemConf.value.baseConf.isReadOnly,class: ['underline_input',{'is-disabled': itemConf.value.baseConf.isReadOnly,},],disabled: itemConf.value.baseConf.isReadOnly,innerHTML: inputValues.value[index],placeholder: unref(itemConf).customConf?.inputGroup[index]?.placeholder || '請輸入',onInput: async (event: InputEvent) => {const target = event.target as HTMLParagraphElement;adjustInputWidth(index);inputValues.value[index] = target.innerHTML;await nextTick(() => {moveCursorToEnd(target);});},onFocus: () => {if (!itemConf.value.baseConf.isReadOnly) {isInputFocused.value[index] = true;clearTimeout(clearIconHideTimer.value[index]);}},onBlur: () => {if (!itemConf.value.baseConf.isReadOnly) {handleChange(itemConf.value.customConf.inputGroup[index], inputValues.value[index]);clearIconHideTimer.value[index] = setTimeout(() => {if (!isClearIconClicked.value[index]) {isInputFocused.value[index] = false;}isClearIconClicked.value[index] = false;}, 200);}},onMousedown: (event: MouseEvent) => {if (itemConf.value.baseConf.isReadOnly) {event.preventDefault();event.stopPropagation();}},onKeydown: (event: KeyboardEvent) => {if (itemConf.value.baseConf.isReadOnly) {event.preventDefault();event.stopPropagation();}},ref: (el) => (inputRefs.value[index] = el),},// [clearIcon],);nodes.push(h('p', { class: 'underline_input_wrap' }, [inputNode, clearIcon]));}});return h('div', nodes);
});

css部分


.underline_input_wrap {display: inline-block;// max-width: calc(100% - 70px);position: relative;margin-top: 20px;margin-bottom: 0;max-width: calc(100% - 50px);
}
.underline_input {position: relative;height: 40px;min-width: 101px;// max-width: calc(100% - 70px);max-width: 100%;background: #f5f7fb;border-radius: 6px 6px 6px 6px;border: none;margin-left: 10px;margin-top: 0;margin-bottom: 0;display: inline-block;box-sizing: border-box;padding: 0 26px 0 12px;background: #f5f7fb;vertical-align: middle;color: #606266;background: #f5f7fb;vertical-align: middle;&:focus {outline: none;border: 1px solid #1a77ff;color: #606266;}&:disabled {color: #bbbfc4;cursor: not-allowed;}&::placeholder {color: #a8abb2;font-size: 14px;}
}.underline_input.is-disabled {color: #bbbfc4;cursor: not-allowed;
}.underline_input[contenteditable='true']:empty::before,
.underline_input.is-disabled:empty::before {content: attr(placeholder);color: #bbbfc4;
}
:deep(.clear_icon) {position: absolute;width: 14px;height: 14px;right: 5px;top: 50%;transform: translateY(-50%);cursor: pointer;color: #999;z-index: 10; /* 增加 z-index 確保在最上層 */&:hover {color: #666;}&.is-hidden {display: none;}
}

我們要模擬input可清除,所以需要我們去調整樣式,以及placeholder樣式問題

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/73959.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/73959.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/73959.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【AI】AI編程助手:Cursor、Codeium、GitHub Copilot、Roo Cline、Tabnine

文章目錄 一、基本特性對比二、收費標準三、私有部署能力1、Tabnine2、Roo Code 三、代碼補全與自然語言生成代碼四、安裝獨立的IDE安裝插件安裝 五、基本使用&#xff08;一&#xff09;Cursor&#xff08;二&#xff09;GitHub Copilot1、獲取代碼建議2.聊天1&#xff09;上下…

三軸云臺之角速度信號篇

三軸云臺的角速度信號主要通過其內置的傳感器&#xff08;如陀螺儀&#xff09;來感知和測量。 一、角速度信號的感知與測量 在三軸云臺中&#xff0c;陀螺儀是測量角速度的關鍵組件。它通常安裝在三個互相垂直的軸上&#xff08;通常為X、Y、Z軸&#xff09;&#xff0c;能夠…

Grid 布局實現三欄布局

使用 CSS Grid 布局實現三欄布局(左右固定 100px,中間自適應)的核心原理是通過網格模板精確控制列寬分配。以下是具體實現方法及優化技巧: 一、基礎實現 ?父容器設置 為外層容器添加 display: grid 使其成為網格容器,并通過 grid-template-columns 定義列寬 css .contain…

綠盟春招實習一面

《網安面試指南》https://mp.weixin.qq.com/s/RIVYDmxI9g_TgGrpbdDKtA?token1860256701&langzh_CN 5000篇網安資料庫https://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247486065&idx2&snb30ade8200e842743339d428f414475e&chksmc0e4732df793fa3bf39…

進制轉換(R轉十)(1290. 二進制轉換十進制、1292. 十六進制轉十進制、1291. 八進制轉十進制、1405. 小麗找潛在的素數)

題單地址&#xff1a;題單中心-東方博宜OJ 這里以二進制轉十進制為例&#xff08;按位加權求和法&#xff09; 1290. 二進制轉換十進制 問題描述 請將一個 25 位以內的 2 進制正整數轉換為 1010 進制&#xff01; 輸入 一個 25 位以內的二進制正整數。 輸出 該數對應的…

Redis 本地安裝

首先安裝&#xff1a; https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-from-source/ 進入root目錄 tar -xzvf redis-stable.tar.gz cd redis-stable make然后 install sudo make install最后可以直接啟動 redis-server但是此時啟…

9.嗅探與Wireshark進階分析

嗅探與Wireshark進階分析 第一部分&#xff1a;嗅探的概念與重要性第二部分&#xff1a;Wireshark進階功能第三部分&#xff1a;嗅探實踐與分析總結 目標&#xff1a; ? 理解嗅探&#xff08;Sniffing&#xff09;的概念及其在網絡安全中的作用 ? 掌握Wireshark的進階功能&a…

在 VSCode 遠程開發環境下使用 Git 常用命令

在日常開發過程中&#xff0c;無論是單人項目還是團隊協作&#xff0c;Git 都是版本管理的利器。尤其是在使用 VSCode 連接遠程服務器進行代碼開發時&#xff0c;Git 不僅能幫助你管理代碼版本&#xff0c;還能讓多人協作變得更加高效。本文將介紹一些常用的 Git 命令&#xff…

npm 命令使用文檔

目錄 簡介安裝與配置基礎命令依賴管理版本控制腳本管理包發布高級命令配置管理最佳實踐常見問題 1. 簡介 npm (Node Package Manager) 是 Node.js 的官方包管理工具&#xff0c;提供&#xff1a; 130萬 開源包的注冊表訪問依賴解析與版本管理項目腳本自動化私有包管理能力完…

【Linux篇】進程控制

&#x1f4cc; 個人主頁&#xff1a; 孫同學_ &#x1f527; 文章專欄&#xff1a;Liunx &#x1f4a1; 關注我&#xff0c;分享經驗&#xff0c;助你少走彎路&#xff01; 1. 進程創建 1.1 fork函數 在linux中fork函數是非常重要的函數&#xff0c;它從已存在進程中創建一個…

HyperAD:學習弱監督音視頻暴力檢測在雙曲空間中的方法

文章目錄 速覽摘要1. 引言2. 相關工作弱監督暴力檢測雙曲空間中的神經網絡 3. 預備知識雙曲幾何切空間&#xff08;Tangent Space&#xff09;指數映射與對數映射&#xff08;Exponential and Logarithmic Maps&#xff09;3.1 雙曲圖卷積網絡&#xff08;Hyperbolic Graph Con…

動態規劃(6.不同路徑II)

題目鏈接&#xff1a;63. 不同路徑 II - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; 本題為不同路徑的變型&#xff0c;只不過有些地方有「障礙物」&#xff0c;只要在「狀態轉移」上稍加修改就可解決。 狀態表示&#xff1a; 對于這種Γ路徑類」的問題&#xf…

深度洞察:DeepSeek 驅動金融行業智能化轉型變革

該文章為軟件測評&#xff0c;不是廣告&#xff01;&#xff01;&#xff01;&#xff01; 目錄 一.金融行業的智能化轉型浪潮? 二.DeepSeek的核心技術剖析 1.DeepSeek 模型的金融智慧? 2.實時聯網搜索&#xff1a;把握金融市場脈搏? 3.RAG 能力&#xff1a;鑄就精準金…

藍橋杯備考----》暴力枚舉---金盞花

這道題&#xff0c;一共12位&#xff0c;給了后六位&#xff0c;我們只要枚舉前六位就行了&#xff0c;當然如果是10的12次方的話&#xff0c;必須要開long long才可以存下&#xff0c;這點我們不要忘了 然后題目中又告訴了沒有前導0&#xff0c;我們可以從100000開始枚舉&…

RAG各類方法python源碼解讀與實踐:利用Jupyter對RAG技術綜合評測【3萬字長文】

檢索增強生成&#xff08;RAG &#xff09;是一種結合信息檢索與生成模型的混合方法。它通過引入外部知識來提升語言模型的性能&#xff0c;從而提高回答的準確性和事實正確性。為了簡單易學&#xff0c;不使用LangChain框架或FAISS向量數據庫&#xff0c;而是利用Jupyter Note…

Python列表2

print("—————————— 列表的相關操作 ————————————")lst.append(x)在列表lst最后增加一個元素 lst.insert(index,x)在列表中第index位置增加一個元素 lst.clear()清除列表lst中所有元素 lst.pop(index)將列表lst中第index位置的元素取出&#xf…

華為OD機試-IPv4地址轉換成整數(Java 2024 B卷 100分)

題目描述 存在一種虛擬 IPv4 地址 Q,由 4 小節組成,每節的范圍為 0~255,以 # 號間隔。虛擬 IPv4 地址可以轉換為一個 32 位的整數。例如: 128#0#255#255 轉換為 32 位整數的結果為 2147549183(0x8000FFFF)1#0#0#0 轉換為 32 位整數的結果為 16777216(0x01000000)現以字…

C語言復習筆記--數組

今天繼續來淺淺推進一下C語言的復習,這次是數組的復習,話不多說,正文開始. 數組的概念 數組是?組相同類型元素的集合,一種自定義類型.數組中元素個數不能為0.數組分為?維數組和多維數組&#xff0c;多維數組?般?較多?的是?維數組. 下面從一維數組說起. 一維數組的創建和…

Canal 解析與 Spring Boot 整合實戰

一、Canal 簡介 1.1 Canal 是什么&#xff1f; Canal 是阿里巴巴開源的一款基于 MySQL 數據庫增量日志解析&#xff08;Binlog&#xff09;中間件&#xff0c;它模擬 MySQL 的從機&#xff08;Slave&#xff09;行為&#xff0c;監聽 MySQL 主機的二進制日志&#xff08;Binl…

《論語別裁》第01章 學而(31) 詩的人生

不過這句話研究起來有一個問題&#xff0c;是詩的問題。我們知道中國文化&#xff0c;在文學的境界上&#xff0c;有一個演變發展的程序&#xff0c;大體的情形&#xff0c;是所謂漢文、唐詩、宋詞、元曲、明小說&#xff0c;到了清朝&#xff0c;我認為是對聯&#xff0c;尤其…