最近在学习基于电子+ electron-vue开发聊天客户端项目时,需要用到编辑器插入表情功能。一般通过输入或文本区域也能实现,通过插入[笑脸),(:12这些标签,展示的时候解析标签就行。
如下图效果:
& lt; !DOCTYPE html> & lt; html> & lt; head> & lt;元charset=皍tf - 8”比; & lt; title> & lt;/title> & lt;链接的href=" https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css " rel=把奖怼北? & lt;/head> & lt; body> & lt; div类="容器"比; & lt; div类="行"比; & lt; div class="坳col-sm-12”比; & lt;按钮类=" btn btn-success " data-emoj="[笑脸]“在[笑脸]& lt;/button> & lt;按钮类=" btn btn-success " data-emoj="[奋斗]“在[奋斗]& lt;/button> & lt;按钮类=" btn btn-success " data-emoj=?17):“在[:17]& lt;/button> & lt;/div> & lt; div class="坳col-sm-12”比; & lt; textarea类="表单控件" id==?0”在“内容”行& lt;/textarea> & lt;/div> & lt;/div> & lt;/div> & lt;脚本src=" https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js "祝辞& lt;/script> & lt; script> (函数(美元){ 美元.fn.extend ({ insertEmojAtCaret:函数(括号){ var t=美元(这)[0]; 如果(document.selection) { this.focus (); 选?document.selection.createRange (); 选取。文本=myValue; this.focus (); }else if ($ t。selectionStart | | $ t。selectionStart==' 0 ') { var startPos=$ t.selectionStart; var endPos=$ t.selectionEnd; var scrollTop=$ t.scrollTop; 美元的t。美元价值=https://www.yisu.com/zixun/t.value.substring (0, startPos) + myValue + t.value美元。substring (endPos t.value.length美元); this.focus (); 美元的t。selectionStart=startPos + myValue.length; 美元的t。selectionEnd=startPos + myValue.length; 美元的t。scrollTop=scrollTop; 其他}{ 这一点。值+=myValue; this.focus (); } } }); }) (jQuery); $("按钮”)。(“点击”,函数(){ $(" #内容”).insertEmojAtCaret($(这).attr (data-emoj ")); }); & lt;/script> & lt;/body> & lt;/html>
可是这种方法并不是我想要的类似微信编辑框插入表情效果。
如是就想到了div模拟设置<代码> contenteditable=" true "> 代码实现富文本编辑器效果,这种方法是可以实现,不过在vue中不能绑定v模型,最后参考一些技术贴实现了这个功能,一顿操作下来采坑不少,于是就做一些分享记录吧。
vue中通过给div添加<代码> contenteditable=true> 代码属性实现富文本功能
& lt; template> … & lt; chatInput ref=" chatInput " v模型=癳ditorText @focusFn”=癶andleEditorFocus”@blurFn=" handleEditorBlur "/比; & lt;/template>
从“进口chatInput。/chatInput ' 出口默认{ 数据(){ 返回{ editorText:”, … } }, 组件:{ chatInput, }, … }
2 v模型中传入的值在子组件道具中获取
出口默认{ 道具:{ 价值:{类型:字符串,默认值:"} }, 数据(){ 返回{ editorText: this.value, … } }, 看:{ 值(){ … } }, }
3,通过监听获取到的道具值,并将该值赋值给子组件中的v-html参数,双向绑定就好了。
chatInput。vue组件
& lt; !——vue实现contenteditable功能,比; & lt; template> & lt; div ref="编辑" 类="编辑" contenteditable=" true " v-html=" editorText " @input=" handleInput " @focus=" handleFocus " @blur=癶andleBlur”比; & lt;/div> & lt;/template> & lt; script> 出口默认{ 道具:{ 价值:{类型:字符串,默认值:"} }, 数据(){ 返回{ editorText: this.value, isChange:没错, } }, 看:{ 值(){ 如果(this.isChange) { 这一点。editorText=this.value } } }, 方法:{ handleInput () { 这一点。美元发出(“输入”,这个。el.innerHTML美元) },//清空编辑器 handleClear () { refs.editor美元。innerHTML=" refs.editor.focus美元。() },//获取焦点 handleFocus () { 这一点。isChange=false 美元。发出(“focusFn”) },//失去焦点 handleBlur () { 这一点。isChange=true 美元。发出(“blurFn”) },/* * *光标处插入内容 * @param html需要插入的内容 */insertHtmlAtCaret (html) { 我们选取范围; 如果(!这。refs.editor.childNodes.length美元){ refs.editor.focus美元。() } 如果(window.getSelection) {//IE9和非ie 选?window.getSelection (); 如果(选取。getRangeAt,,sel.rangeCount) {=sel.getRangeAt范围(0); range.deleteContents (); 让el=document.createElement (" div "); el.appendChild (html) var=document.createDocumentFragment干掉()、节点lastNode; 在((节点=el.firstChild)) { lastNode=frag.appendChild(节点); } range.insertNode(破片); 如果(lastNode) { 范围=range.cloneRange (); range.setStartAfter (lastNode); range.collapse(真正的); sel.removeAllRanges (); sel.addRange(范围); } } }如果(文档。选择,,document.selection。类型!=翱刂啤?{//IE & lt;9 document.selection.createRange () .pasteHTML (html); } this.handleInput () } } } & lt;/script> & lt; style> & lt;/style>电子+ vue实现div contenteditable截图功能