vue3使用自定義指令實(shí)現(xiàn)eldialog拖拽功能示例詳解_第1頁
vue3使用自定義指令實(shí)現(xiàn)eldialog拖拽功能示例詳解_第2頁
vue3使用自定義指令實(shí)現(xiàn)eldialog拖拽功能示例詳解_第3頁
vue3使用自定義指令實(shí)現(xiàn)eldialog拖拽功能示例詳解_第4頁
vue3使用自定義指令實(shí)現(xiàn)eldialog拖拽功能示例詳解_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第vue3使用自定義指令實(shí)現(xiàn)eldialog拖拽功能示例詳解目錄實(shí)現(xiàn)el-dialog的拖拽功能通過自定義指令實(shí)現(xiàn)拖拽功能實(shí)現(xiàn)拖拽功能使用方式

實(shí)現(xiàn)el-dialog的拖拽功能

這里指的是element-plus的el-dialog組件,一開始該組件并沒有實(shí)現(xiàn)拖拽的功能,當(dāng)然現(xiàn)在可以通過設(shè)置屬性的方式實(shí)現(xiàn)拖拽。

自帶的拖拽功能非常嚴(yán)謹(jǐn),拖拽時判斷是否拖拽出窗口,如果出去了會阻止拖拽。

如果自帶的拖拽功能可以滿足需求的話,可以跳過本文。

通過自定義指令實(shí)現(xiàn)拖拽功能

因?yàn)橐约翰僮鱠om(設(shè)置事件),所以感覺還是使用自定義指令更直接一些,而且對原生組件的影響更小。

我們先定義一個自定義指令_dialogDrag:

importdialogDragfrom'./_dialog-drag'

import{watch}from'vue'

const_dialogDrag={

//mounted

mounted(el:any,binding:any){

//監(jiān)聽dialog是否顯示的狀態(tài)

watch(binding.value,()={

//dialog不可見,退出

if(!binding.value.visible)return

//尋找el-dialog組件

constcontainer=el.firstElementChild.firstElementChild

//已經(jīng)設(shè)置拖拽事件,退出

if(container.onmousemove)return

//等待DOM渲染完畢

setTimeout(()={

//拖拽的“句柄”

const_dialogTitle=el.getElementsByClassName('el-dialog__header')

if(_dialogTitle.length===0){

//還沒有渲染完畢,或則其他原因

console.warn('沒有找到要拖拽的el-dialog',el)

}else{

const{setDialog}=dialogDrag()

constdialogTitle=_dialogTitle[0]

//彈窗

constdialog=el.firstElementChild.firstElementChild.firstElementChild

//通過css尋找el-dialog設(shè)置的寬度

constarr=dialog.style.cssText.split(';')

constwidth=arr[0].replace('%','').replace('--el-dialog-width:','')//

//設(shè)置el-dialog組件、彈窗、句柄、寬度

setDialog(container,dialog,dialogTitle,width)

},300)

*注冊拖拽dialog的自定義指令

*@paramapp

*@paramoptions

constinstall=(app:any,options:any)={

app.directive('dialogDrag',_dialogDrag)

export{

_dialogDrag,

install

這里有兩個比較煩人的地方:

DOM渲染完畢的時機(jī)。執(zhí)行mounted的時候,DOM不一定渲染完畢,如果不使用setTimeout的話,就會找不到DOM,所以用了這種笨辦法。dialog的隱藏。一般情況下,el-dialog初始是隱藏狀態(tài),隱藏了就意味著DOM并不會被渲染出來??墒亲远x指令會在一開始即被執(zhí)行,這時setTimeout的等待時間再長也無用,所以只好監(jiān)聽dialog的狀態(tài)。ref通過template傳遞后,再次傳入組件的話,就會失去ref的那一層的響應(yīng)性,所以只能傳入reactive才行,這樣調(diào)用指令的組件,就會比較別扭,目前沒有想到更好的實(shí)現(xiàn)方式。

實(shí)現(xiàn)拖拽功能

定義指令和實(shí)現(xiàn)拖拽,我分成了兩個文件,我想,盡量解耦一下。

定義一個拖拽函數(shù)(dialogDrag):

/**

*拖拽dialog的函數(shù),目前支持element-plus

exportdefaultfunctiondialogDrag(){

*設(shè)置拖拽事件

*@paramcontainer大容器,比如蒙版。

*@paramdialog被拖拽的窗口

*@paramdialogTitle拖拽的標(biāo)題

*@paramwidth寬度比例

constsetDialog=(container:any,dialog:any,dialogTitle:any,width:number)={

constoldCursor=dialogTitle.style.cursor

//可視窗口的寬度

constclientWidth=document.documentElement.clientWidth

//可視窗口的高度

constclientHeight=document.documentElement.clientHeight

//根據(jù)百分?jǐn)?shù)計算寬度

consttmpWidth=clientWidth*(100-width)/200

//默認(rèn)寬度和高度

constdomset={

x:tmpWidth,

y:clientHeight*15/100//根據(jù)15vh計算

//查看dialog當(dāng)前的寬度和高低

if(dialog.style.marginLeft===''){

dialog.style.marginLeft=domset.x+'px'

}else{

domset.x=dialog.style.marginLeft.replace('px','')*1

if(dialog.style.marginTop===''){

dialog.style.marginTop=domset.y+'px'

}else{

domset.y=dialog.style.marginTop.replace('px','')*1

//記錄拖拽開始的光標(biāo)坐標(biāo),0表示沒有拖拽

conststart={x:0,y:0}

//移動中記錄偏移量

constmove={x:0,y:0}

//經(jīng)過時改變鼠標(biāo)指針形狀

dialogTitle.onmouseover=()={

dialogTitle.style.cursor='move'//改變光標(biāo)形狀

//鼠標(biāo)按下,開始拖拽

dialogTitle.onmousedown=(e:any)={

start.x=e.clientX

start.y=e.clientY

dialogTitle.style.cursor='move'//改變光標(biāo)形狀

//鼠標(biāo)移動,實(shí)時跟蹤dialog

container.onmousemove=(e:any)={

if(start.x===0){//不是拖拽狀態(tài)

return

move.x=e.clientX-start.x

move.y=e.clientY-start.y

//初始位置+拖拽距離

dialog.style.marginLeft=(domset.x+move.x)+'px'

dialog.style.marginTop=(domset.y+move.y)+'px'

//鼠標(biāo)抬起,結(jié)束拖拽

container.onmouseup=(e:any)={

if(start.x===0){//不是拖拽狀態(tài)

return

move.x=e.clientX-start.x

move.y=e.clientY-start.y

//記錄新坐標(biāo),作為下次拖拽的初始位置

domset.x+=move.x

domset.y+=move.y

dialogTitle.style.cursor=oldCursor

dialog.style.marginLeft=domset.x+'px'

dialog.style.marginTop=domset.y+'px'

//結(jié)束拖拽

start.x=0

return{

setDialog//設(shè)置

首先觀察el-dialog渲染后的DOM結(jié)構(gòu),發(fā)現(xiàn)是通過marginLeft、marginTop這兩個css的屬性,那么我們的拖拽也可以通過修改這兩個屬性來實(shí)現(xiàn)。

然后就是古老的拖拽思路:按下鼠標(biāo)的時候,記錄光標(biāo)的初始坐標(biāo),抬起鼠標(biāo)的時候,記錄光標(biāo)的結(jié)束坐標(biāo),然后計算一下得到x、y的偏移量,進(jìn)而修改marginLeft、marginTop這兩個屬性,即可實(shí)現(xiàn)拖拽的效果。

核心思路就是這樣,剩下的就是細(xì)節(jié)完善了。

還有一個小問題,拖拽后關(guān)閉,然后再次打開,希望可以在拖拽結(jié)束的地方打開,而不是默認(rèn)的位置。所以又想了個辦法記錄這個位置。

還是要觀察el-dialog的行為,最后發(fā)現(xiàn)規(guī)律,一開始marginLeft是空的,而拖拽后會保留位置。所以,判斷一下就好。

使用方式

原本想直接給el-dialog設(shè)置自定義指令,但是發(fā)現(xiàn)無效,所以只好在外面套個div。

template

!--拖拽--

el-button@click="dialog.visible=true"打開/el-button

divv-dialog-drag="dialog"

el-dialog

v-model="dialog.visible"

title="自定義拖拽2"

width="25%"

span拖拽測試/span

template#footer

span

el-button@click="dialog.visible=false"Cancel/el-button

el-buttontype="primary"@click="dialog.visible=false"Confirm/el-button

/span

/template

/el-dialog

/div

/template

scriptlang="ts"

import{defineComponent,ref,reactive}from'vue'

import{_dialogDrag}from'../../../lib/main'

exportdefaultdefineComponent({

name:'nf-dialog-move',

directives:{

dialogDrag:_dialogDrag

props:{

setup(props,context){

constdialog=reactive({

visible:false

return{

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論