Vue實現圖片與文字混輸🔥
知識在於積累,踩坑越多,你越強😎
前言
用多了JQuery,習慣了使用JQuery的API操作DOM,幾乎忘記了原生JS對DOM操作,今天在項目中遇到了文字和圖片混輸的情況,第一個想到的辦法是用textarea實現,結果發現實現不了圖片輸入,然后想着找個富文本編輯器的插件實現,深思熟慮之后,我的需求好像也沒那么復雜,不至於引用個插件,看了掘金的發布沸點功能,然后就模仿了其作法,於是就有了這篇文章的分享。先給大家展示下最后實現的效果😋
實現思路
- 利用div的contenteditable屬性,讓div可編輯
- 綁定ref屬性,用於操作輸入框元素
- 圖片點擊時,獲取圖片地址,使用require轉換圖片地址
- 創建img標簽,賦值轉換好的圖片地址
- 從refs對象中獲取到輸入框元素,賦值創建好的img標簽
實現過程
- 聲明div可編輯,監聽回車鍵事件,關閉拼寫檢查,綁定ref方便獲取當前元素
<div class="input-panel" ref="msgInputContainer" @keydown.enter.exact="sendMessage($event)" contenteditable="true" spellcheck="false"></div> 復制代碼 - 表情輸入框綁定對應的事件
<div class="item-panel" v-for="item in this.emojiList" :key="item.info"> <img :src="require(`../assets/img/emoji/${item.src}`)" :alt="item.info" @mouseover="emojiConversion($event,'over',item.src,item.hover,item.info)" @mouseleave="emojiConversion($event,'leave',item.src,item.hover,item.info)" @click="emojiConversion($event,'click',item.src,item.hover,item.info)"> </div> 復制代碼 - 實現表情框圖片點擊事件
emojiConversion: function (event, status, path, hoverPath, info) { if (status === "over") { event.target.src = require(`../assets/img/emoji/${hoverPath}`); } else if (status === "click") { // 表情輸入 const imgSrc = require(`../assets/img/emoji/${hoverPath}`); /** * 不推薦的寫法: * 無法獲取焦點 * 無法在當前焦點的位置插入元素 */ // const imgTag = document.createElement("img"); // imgTag.src = imgSrc; // imgTag.alt = info; // this.$refs.msgInputContainer.appendChild(imgTag); /** * 推薦使用document暴露的execCommand 方法來操作此處 * 可以在當前焦點處插入元素 * 感謝評論區掘友的建議 */ const imgTag = `<img src="${imgSrc}" width="28" height="28" alt="${info}">`; document.execCommand("insertHTML", false, imgTag); } else { event.target.src = require(`../assets/img/emoji/${path}`); } } 復制代碼
踩坑記錄
-
直接使用append()方法
公司項目一直用JQuery,類似的需求直接append,以為是js提供的方法,結果這里直接使用,答案很明顯,直接將DOM字符串插入了輸入框里🤣
-
手動實現字符串轉dom
自己手動實現,不知道是不是自己寫錯了,結果也是行不通,如果有發現錯誤的朋友,歡迎評論區留言。
-
正確的實現方法
創建DOM字符串,使用document暴露的execCommand方法來插入創建好的DOM字符串。使用方法
- 不過execCommand的兼容性欠佳,如果遇到沒反應的情況,是你的瀏覽器不支持此api。(圖片源自mdn)
- 如果考慮兼容性問題可使用文中提到的另一種寫法
// const imgTag = document.createElement("img"); // imgTag.src = imgSrc; // imgTag.alt = info; // this.$refs.msgInputContainer.appendChild(imgTag);
