怎样通过Vue实现@人的功能(vue,开发技术)

时间:2024-05-05 04:58:11 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

下面采用vue,同时增加鼠标点击事件和一些页面小优化

怎样通过Vue实现@人的功能

怎样通过Vue实现@人的功能

基本结构

新建一个sandBox.vue文件编写功能的基本结构

<divclass="content"><!--文本框--><divclass="editor"ref="divRef"contenteditable@keyup="handkeKeyUp"@keydown="handleKeyDown"></div><!--选项--><AtDialogv-if="showDialog":visible="showDialog":position="position":queryString="queryString"@onPickUser="handlePickUser"@onHide="handleHide"@onShow="handleShow"></AtDialog></div><script>importAtDialogfrom'../components/AtDialog'exportdefault{name:'sandBox',components:{AtDialog},data(){return{node:'',//获取到节点user:'',//选中项的内容endIndex:'',//光标最后停留位置queryString:'',//搜索值showDialog:false,//是否显示弹窗position:{x:0,y:0}//弹窗显示位置}},methods:{//获取光标位置getCursorIndex(){constselection=window.getSelection()returnselection.focusOffset//选择开始处focusNode的偏移量},//获取节点getRangeNode(){constselection=window.getSelection()returnselection.focusNode//选择的结束节点},//弹窗出现的位置getRangeRect(){constselection=window.getSelection()constrange=selection.getRangeAt(0)//是用于管理选择范围的通用对象constrect=range.getClientRects()[0]//择一些文本并将获得所选文本的范围constLINE_HEIGHT=30return{x:rect.x,y:rect.y+LINE_HEIGHT}},//是否展示@showAt(){constnode=this.getRangeNode()if(!node||node.nodeType!==Node.TEXT_NODE)returnfalseconstcontent=node.textContent||''constregx=/@([^@\s]*)$/constmatch=regx.exec(content.slice(0,this.getCursorIndex()))returnmatch&&match.length===2},//获取@用户getAtUser(){constcontent=this.getRangeNode().textContent||''constregx=/@([^@\s]*)$/constmatch=regx.exec(content.slice(0,this.getCursorIndex()))if(match&&match.length===2){returnmatch[1]}returnundefined},//创建标签createAtButton(user){constbtn=document.createElement('span')btn.style.display='inline-block'btn.dataset.user=JSON.stringify(user)btn.className='at-button'btn.contentEditable='false'btn.textContent=`@${user.name}`constwrapper=document.createElement('span')wrapper.style.display='inline-block'wrapper.contentEditable='false'constspaceElem=document.createElement('span')spaceElem.style.whiteSpace='pre'spaceElem.textContent='\u200b'spaceElem.contentEditable='false'constclonedSpaceElem=spaceElem.cloneNode(true)wrapper.appendChild(spaceElem)wrapper.appendChild(btn)wrapper.appendChild(clonedSpaceElem)returnwrapper},replaceString(raw,replacer){returnraw.replace(/@([^@\s]*)$/,replacer)},//插入@标签replaceAtUser(user){constnode=this.nodeif(node&&user){constcontent=node.textContent||''constendIndex=this.endIndexconstpreSlice=this.replaceString(content.slice(0,endIndex),'')constrestSlice=content.slice(endIndex)constparentNode=node.parentNodeconstnextNode=node.nextSiblingconstpreviousTextNode=newText(preSlice)constnextTextNode=newText('\u200b'+restSlice)//添加0宽字符constatButton=this.createAtButton(user)parentNode.removeChild(node)//插在文本框中if(nextNode){parentNode.insertBefore(previousTextNode,nextNode)parentNode.insertBefore(atButton,nextNode)parentNode.insertBefore(nextTextNode,nextNode)}else{parentNode.appendChild(previousTextNode)parentNode.appendChild(atButton)parentNode.appendChild(nextTextNode)}//重置光标的位置constrange=newRange()constselection=window.getSelection()range.setStart(nextTextNode,0)range.setEnd(nextTextNode,0)selection.removeAllRanges()selection.addRange(range)}},//键盘抬起事件handkeKeyUp(){if(this.showAt()){constnode=this.getRangeNode()constendIndex=this.getCursorIndex()this.node=nodethis.endIndex=endIndexthis.position=this.getRangeRect()this.queryString=this.getAtUser()||''this.showDialog=true}else{this.showDialog=false}},//键盘按下事件handleKeyDown(e){if(this.showDialog){if(e.code==='ArrowUp'||e.code==='ArrowDown'||e.code==='Enter'){e.preventDefault()}}},//插入标签后隐藏选择框handlePickUser(user){this.replaceAtUser(user)this.user=userthis.showDialog=false},//隐藏选择框handleHide(){this.showDialog=false},//显示选择框handleShow(){this.showDialog=true}}}</script><stylescopedlang="scss">.content{font-family:sans-serif;h2{text-align:center;}}.editor{margin:0auto;width:600px;height:150px;background:#fff;border:1pxsolidblue;border-radius:5px;text-align:left;padding:10px;overflow:auto;line-height:30px;&:focus{outline:none;}}</style>

如果添加了点击事件,节点和光标位置获取,需要在【键盘抬起事件】中获取,并保存到data

//键盘抬起事件handkeKeyUp(){if(this.showAt()){constnode=this.getRangeNode()//获取节点constendIndex=this.getCursorIndex()//获取光标位置this.node=nodethis.endIndex=endIndexthis.position=this.getRangeRect()this.queryString=this.getAtUser()||''this.showDialog=true}else{this.showDialog=false}},

新建一个组件,编辑弹窗选项

<template><divclass="wrapper":><divv-if="!mockList.length"class="empty">无搜索结果</div><divv-for="(item,i)inmockList":key="item.id"class="item":class="{'active':i===index}"ref="usersRef"@click="clickAt($event,item)"@mouseenter="hoverAt(i)"><divclass="name">{{item.name}}</div></div></div></template><script>constmockData=[{name:'HTML',id:'HTML'},{name:'CSS',id:'CSS'},{name:'Java',id:'Java'},{name:'JavaScript',id:'JavaScript'}]exportdefault{name:'AtDialog',props:{visible:Boolean,position:Object,queryString:String},data(){return{users:[],index:-1,mockList:mockData}},watch:{queryString(val){val?this.mockList=mockData.filter(({name})=>name.startsWith(val)):this.mockList=mockData.slice(0)}},mounted(){document.addEventListener('keyup',this.keyDownHandler)},destroyed(){document.removeEventListener('keyup',this.keyDownHandler)},methods:{keyDownHandler(e){if(e.code==='Escape'){this.$emit('onHide')return}//键盘按下=>↓if(e.code==='ArrowDown'){if(this.index>=this.mockList.length-1){this.index=0}else{this.index=this.index+1}}//键盘按下=>↑if(e.code==='ArrowUp'){if(this.index<=0){this.index=this.mockList.length-1}else{this.index=this.index-1}}//键盘按下=>回车if(e.code==='Enter'){if(this.mockList.length){constuser={name:this.mockList[this.index].name,id:this.mockList[this.index].id}this.$emit('onPickUser',user)this.index=-1}}},clickAt(e,item){constuser={name:item.name,id:item.id}this.$emit('onPickUser',user)this.index=-1},hoverAt(index){this.index=index}}}</script><stylescopedlang="scss">.wrapper{width:238px;border:1pxsolid#e4e7ed;border-radius:4px;background-color:#fff;box-shadow:02px12px0rgb(000/10%);box-sizing:border-box;padding:6px0;}.empty{font-size:14px;padding:020px;color:#999;}.item{font-size:14px;padding:020px;line-height:34px;cursor:pointer;color:#606266;&.active{background:#f5f7fa;color:blue;.id{color:blue;}}&:first-child{border-radius:5px5px00;}&:last-child{border-radius:005px5px;}.id{font-size:12px;color:rgb(83,81,81);}}</style>
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:怎样通过Vue实现@人的功能的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:移动开发中自动化测试的示例分析下一篇:

4 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18