




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第如何通過Vue實(shí)現(xiàn)@人的功能本文采用vue,同時(shí)增加鼠標(biāo)點(diǎn)擊事件和一些頁(yè)面小優(yōu)化
基本結(jié)構(gòu)
新建一個(gè)sandBox.vue文件編寫功能的基本結(jié)構(gòu)
div
!--文本框--
ref="divRef"
contenteditable
@keyup="handkeKeyUp"
@keydown="handleKeyDown"
/div
!--選項(xiàng)--
AtDialog
v-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:'',//獲取到節(jié)點(diǎn)
user:'',//選中項(xiàng)的內(nèi)容
endIndex:'',//光標(biāo)最后停留位置
queryString:'',//搜索值
showDialog:false,//是否顯示彈窗
position:{
x:0,
y:0
}//彈窗顯示位置
methods:{
//獲取光標(biāo)位置
getCursorIndex(){
constselection=window.getSelection()
returnselection.focusOffset//選擇開始處focusNode的偏移量
//獲取節(jié)點(diǎn)
getRangeNode(){
constselection=window.getSelection()
returnselection.focusNode//選擇的結(jié)束節(jié)點(diǎn)
//彈窗出現(xiàn)的位置
getRangeRect(){
constselection=window.getSelection()
constrange=selection.getRangeAt(0)//是用于管理選擇范圍的通用對(duì)象
constrect=range.getClientRects()[0]//擇一些文本并將獲得所選文本的范圍
constLINE_HEIGHT=30
return{
x:rect.x,
y:rect.y+LINE_HEIGHT
//是否展示@
showAt(){
constnode=this.getRangeNode()
if(!node||node.nodeType!==Node.TEXT_NODE)returnfalse
constcontent=node.textContent||''
constregx=/@([^@\s]*)$/
constmatch=regx.exec(content.slice(0,this.getCursorIndex()))
returnmatchmatch.length===2
//獲取@用戶
getAtUser(){
constcontent=this.getRangeNode().textContent||''
constregx=/@([^@\s]*)$/
constmatch=regx.exec(content.slice(0,this.getCursorIndex()))
if(matchmatch.length===2){
returnmatch[1]
returnundefined
//創(chuàng)建標(biāo)簽
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=`@${}`
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)
//插入@標(biāo)簽
replaceAtUser(user){
constnode=this.node
if(nodeuser){
constcontent=node.textContent||''
constendIndex=this.endIndex
constpreSlice=this.replaceString(content.slice(0,endIndex),'')
constrestSlice=content.slice(endIndex)
constparentNode=node.parentNode
constnextNode=node.nextSibling
constpreviousTextNode=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)
//重置光標(biāo)的位置
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=node
this.endIndex=endIndex
this.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()
//插入標(biāo)簽后隱藏選擇框
handlePickUser(user){
this.replaceAtUser(user)
this.user=user
this.showDialog=false
//隱藏選擇框
handleHide(){
this.showDialog=false
//顯示選擇框
handleShow(){
this.showDialog=true
/script
stylescopedlang="scss"
.content{
font-family:sans-serif;
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
如果添加了點(diǎn)擊事件,節(jié)點(diǎn)和光標(biāo)位置獲取,需要在【鍵盤抬起事件】中獲取,并保存到data
//鍵盤抬起事件
handkeKeyUp(){
if(this.showAt()){
constnode=this.getRangeNode()//獲取節(jié)點(diǎn)
constendIndex=this.getCursorIndex()//獲取光標(biāo)位置
this.node=node
this.endIndex=endIndex
this.position=this.getRangeRect()
this.queryString=this.getAtUser()||''
this.showDialog=true
}else{
this.showDialog=false
},
新建一個(gè)組件,編輯彈窗選項(xiàng)
template
:style="{position:'fixed',top:position.y+'px',left:position.x+'px'}"
divv-if="!mockList.length"無搜索結(jié)果/div
v-for="(item,i)inmockList"
:key="item.id"
:class="{'active':i===index}"
ref="usersRef"
@click="clickAt($event,item)"
@mouseenter="hoverAt(i)"
div{{}}/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){
valthis.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:,
id:item.id
this.$emit('onPickUser',user)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 新疆農(nóng)村六一活動(dòng)方案
- 新品巡展活動(dòng)方案
- 春節(jié)工會(huì)走訪活動(dòng)方案
- 春節(jié)氛圍活動(dòng)方案
- 數(shù)字媒體展廳活動(dòng)方案
- 教育公司培訓(xùn)課件
- 春季團(tuán)建訓(xùn)練活動(dòng)方案
- 春節(jié)比亞迪活動(dòng)方案
- 文化熏陶促育活動(dòng)方案
- 新品上市優(yōu)惠券活動(dòng)方案
- SDS汽油安全技術(shù)說明書
- 【企業(yè)安全管理】粉塵涉爆企業(yè)安全培訓(xùn)
- GeneralEnglish-入學(xué)測(cè)試(劍橋五級(jí))附有答案
- 教海探航論文
- IPC-A-610國(guó)際標(biāo)準(zhǔn)中英文對(duì)照(doc 17)
- JJF(建材)110-2019水泥雷氏夾膨脹測(cè)定儀校準(zhǔn)規(guī)范-(高清現(xiàn)行)
- 《納尼亞傳奇》閱讀交流(課堂PPT)
- 某航空公司教學(xué)材料之十八案例
- 縣級(jí)課題研究過程記錄
- 中山大學(xué)綜合評(píng)價(jià)招生綜合素質(zhì)測(cè)試題總結(jié)
- 預(yù)制場(chǎng)(梁場(chǎng))建設(shè)方案
評(píng)論
0/150
提交評(píng)論