首页IT科技富文本内容原样输出(富文本实现@选择人)

富文本内容原样输出(富文本实现@选择人)

时间2025-06-20 13:19:55分类IT科技浏览4696
导读:准备工作...

准备工作

组件:

<!--富文本--> <div :id="editorEleId" @keydown="onKeyDownInput($event)" @click="onClickEditor" ></div> <!-- 成员选择 --> <div class="userPopupList" :style="{left: left + px, top: top + px}" v-show="show"> <el-input v-model="userName" ref="input"></el-input> <ul> <li v-for="user in protectPersons.filter((item) => item.workNick.includes(this.userName))" :key="user.userId" @click="createSelectElement(user.workNick,user.userId)" > <el-avatar :size="22" :src="user.icon" class="m-r-10" style="vertical-align: middle" > <img src="../../assets/images/defaultIcon.gif"/> </el-avatar> <span>{{user.workNick}}</span> </li> </ul> </div>
.userPopupList{ position: fixed; z-index: 9999; /deep/input{ border:none; background: transparent; } ul{ max-height: 200px; overflow-y: auto; border: 1px solid #dbdada; background: #fff; padding: 10px 10px 0; border-radius: 3px; li{ margin-bottom: 5px; padding: 5px 10px; &:hover{ background: #f6f5f5; } } } }
position:any = {}; left:number = 0; top:number = 0; show:boolean = false; isRendering: boolean = false; userName: string = ; users:any = []; ...富文本初始化 this.editor.config.onchange = () => { // 生成@的标签的时候会触发渲染            、此时不要记录光标坐标 if (this.isRendering === false) { this.setRecordCoordinates() // 记录坐标 }else { this.isRendering = false; }}; // 每次点击获取更新坐标onClickEditor() { this.setRecordCoordinates()}// 获取当前光标坐标setRecordCoordinates() { try { // getSelection() 返回一个 Selection 对象            ,表示用户选择的文本范围或光标的当前位置            。 if(!this.show){       const selection:any = window.getSelection();       this.position = {       range: selection.getRangeAt(0),       selection: selection       }      } } catch (error) { console.log(error, 光标获取失败了~) }}// keydown触发事件 记录光标onKeyDownInput(e:any) { const isCode = ((e.keyCode === 229 && e.key === @) || (e.keyCode === 229 && e.code === Digit2) || e.keyCode === 50) && e.shiftKey if (isCode) { this.setRecordCoordinates(); // 保存坐标 this.getPosition(); // 显示选择框                   ,定时原因:1                   、@会插入到input中      ,2      、光标位置也是input的         ,会导致插入位置错误 setTimeout(()=>{ this.show = true this.$nextTick(()=>{ (this.$refs.input as any).focus(); }) },200) }}//弹窗列表 - 选人 - 生成@的内容createSelectElement(name:string, id:string, type = default) { // 获取当前文本光标的位置                  。 const { range } = this.position // 生成需要显示的内容 let spanNodeFirst:any = document.createElement(span) spanNodeFirst.className = user-node spanNodeFirst.style.color = #409EFF spanNodeFirst.innerHTML = `@${name}&nbsp;` // @的文本信息 spanNodeFirst.dataset.id = id // 用户ID         、为后续解析富文本提供 spanNodeFirst.contentEditable = false // 当设置为false时                   ,富文本会把成功文本视为一个节点       。 // 需要在字符前插入一个空格否则                   、在换行与两个@标签连续的时候导致无法删除标签 let spanNode = document.createElement(span); spanNode.innerHTML = &nbsp;; //创建一个新的空白的文档片段         ,拆入对应文本内容 let frag = document.createDocumentFragment() frag.appendChild(spanNode); frag.appendChild(spanNodeFirst); frag.appendChild(spanNode); // 如果是键盘触发的默认删除面前的@      ,前文中我们没有阻止@的生成所以要删除@的再插入ps:如果你是数组遍历的请传入type 不然会一直删除你前面的字符         。 if (type === default) { const textNode = range.startContainer; range.setStart(textNode, range.endOffset - 1); range.setEnd(textNode, range.endOffset); range.deleteContents(); } this.isRendering = true; // 判断是否有文本         、是否有坐标 if ((this.editor.txt.text() || type === default)&& this.position && range) { range.insertNode(frag) } else { // 如果没有内容一开始就插入数据特别处理 this.editor.txt.append(`<span data-id="${id}" contentEditable="false">@${name}&nbsp;</span>`) } this.show = false; this.userName = ;}// 获取当前光标位置getPosition () { const ele:any = this.editor.$textElem.elems[0]; const pos = position(ele) const off = offset(ele) const parentW = ele.offsetWidth // 这个是弹窗列表 const childEle:any = document.getElementsByClassName("userPopupList") const childW = childEle.offsetWidth // 弹框偏移超出父元素的宽高 if (parentW - pos.left < childW) { this.left = off.left - childW } else { this.left = off.left } this.top = off.top - 4} //提交评论sure(ev: any) { ... const users = document.querySelectorAll(.user-node); let userIds:string[] = []; users.forEach((item:any) => { userIds.push(item.getAttribute(data-id)) }) ...}
声明:本站所有文章                   ,如无特殊说明或标注            ,均为本站原创发布                  。任何个人或组织   ,在未征得本站同意时                   ,禁止复制      、盗用                   、采集            、发布本站内容到任何网站   、书籍等各类媒体平台          。如若本站内容侵犯了原著者的合法权益               ,可联系我们进行处理      。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
如何调用模板函数(使用类模板实现STL Vector)