您好,登錄后才能下訂單哦!
小編給大家分享一下vue中引入mousewheel事件及兼容性處理方式的示例分析,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
項(xiàng)目實(shí)現(xiàn)過程中需要對一個已經(jīng)有縱向滾動條的table表格增加鼠標(biāo)滾輪(mousewheel)事件,方便查看數(shù)據(jù);其實(shí)現(xiàn)原理與我上一篇博客中的拖動事件類似,利用模擬出來的同一個滾動條來實(shí)現(xiàn)
1、滾動條與滾動槽的高度比例 應(yīng)該等于 內(nèi)容區(qū)(動態(tài)變化)和可視區(qū)的高度比例;滾動槽與可視區(qū)平齊,高度一樣;滾動條的高度則根據(jù)內(nèi)容的高度等比例計(jì)算;
2、各元素的定位采用絕對定位,其父元素采用相對定位,這樣就能很好地設(shè)置樣式;
布局與樣式做好后,只需要在組件methods注冊方法,在元素就位后調(diào)用該方法,在方法內(nèi)部為表格綁定(mousewheel)事件;在這里需要考慮兼容性問題,firefox并不支持mousewheel事件,它對應(yīng)的鼠標(biāo)滾動事件為DOMMouseScroll事件,并且該事件僅能通過DOM2級(addEventListener)添加處理程序;并且判斷鼠標(biāo)滾動方向的方式也不一樣,firefoxt通過detail屬性判斷,向前滾動該屬性為-3,向后+3;其余瀏覽器通過wheelDelta屬性,向前時(shí)為+120的倍數(shù),向后為-120的倍數(shù);
具體內(nèi)容可參考《js高級程序設(shè)計(jì)》事件一章;添加函數(shù)如下:
scroll(){ this.wrapDiv = document.getElementById("wrap"); this.contentDiv = document.getElementById("context-table"); this.contentDiv1 = document.getElementById("context-table1"); this.sliderWrap = document.getElementById("sliderWrap"); this.slider = document.getElementById("slider"); //設(shè)置比例 let scale = this.wrapDiv.clientHeight / this.contentDiv.clientHeight; if (scale < 1) { this.mouseFlag = true; let h2 = this.sliderWrap.clientHeight * scale; h2 = (h2 < 50) ? 50 : h2; this.slider.style.height = h2 + "px";/*滾動條高度動態(tài)變化*/ let y = 0; let that = this; //為firefox添加滾輪事件 if (document.addEventListener){ document.addEventListener('DOMMouseScroll',function (e) { if(that.mouseFlag){ //console.log('scroll'); let event1 = window.event|| e; y = (event1.detail > 0) ? y + 8 : y - 8; y = (y < 0) ? 0 : y; let max = that.sliderWrap.clientHeight - that.slider.clientHeight; y = (y > max + 1) ? max + 1 : y; that.slider.style.top = y + "px"; scale = that.wrapDiv.clientHeight / that.contentDiv.clientHeight; let y1 = -y / scale; that.contentDiv.style.top = y1 + "px"; that.contentDiv1.style.top = y1 + "px"; } },false) } this.wrapDiv.onmousewheel = function (e) { if (scale < 1) { let event1 = window.event || e; y = (event1.wheelDelta < 0) ? y + 8 : y - 8; y = (y < 0) ? 0 : y;/*限定滾動范圍*/ let max = that.sliderWrap.clientHeight - that.slider.clientHeight; //console.log(scale, y, sliderWrap.clientHeight, slider.clientHeight); y = (y > max + 1) ? max + 1 : y; that.slider.style.top = y + "px"; scale = that.wrapDiv.clientHeight / that.contentDiv.clientHeight; let y1 = -y / scale; that.contentDiv.style.top = y1 + "px"; that.contentDiv1.style.top = y1 + "px"; } } } else{/*當(dāng)內(nèi)容區(qū)高度小于等于可視區(qū)時(shí),去除綁定的事件和滾動條*/ this.wrapDiv.onmousewheel =null; if(document.addEventListener){ this.mouseFlag = false; } this.sliderWrap.style.visibility = 'hidden'; let height = this.contentDiv.clientHeight; tableRight.style.height = height+72+'px'; this.wrapDiv.style.height = height+2+'px'; } },
該函數(shù)在給firefox綁定的事件解綁時(shí)遇到了問題,由于removeEventListener()需要通過句柄來解綁,而addEventListener()通過句柄添加處理函數(shù)會導(dǎo)致event參數(shù)無法傳遞的問題;即使在需要解綁時(shí)給document綁定空的處理函數(shù)也無法覆蓋前一個綁定函數(shù);最后只好添加一個標(biāo)志,在需要解綁函數(shù)時(shí)改變標(biāo)志的值;在綁定函數(shù)中通過判斷該標(biāo)志的值來確定是否要做操作;
通過上述方式即可很好地實(shí)現(xiàn)鼠標(biāo)滾動事件的效果,并不會有兼容性的問題出現(xiàn)。
注:若僅僅是為表格綁定單一的滾動事件,則可以不顯示滾動條,甚至不設(shè)置滾動條;滾動條的作用僅僅是用來指示內(nèi)容區(qū)滾動的位置,以及配合拖動事件使用;
火狐的鼠標(biāo)滾輪事件是DOMMouseScroll
事件參數(shù)兼容:e=window.event||e;(下面省略)
preventDefault()函數(shù)取消的是默認(rèn)事件,不會把我們自己添加的事件處理刪除
在下面驗(yàn)證例子的基礎(chǔ)上實(shí)驗(yàn),實(shí)驗(yàn)之間代碼沒有干涉:
1.原樣輸出
在元素內(nèi)無論是手動拉動滾動條還是滾動鼠標(biāo)滾輪,'d'都是無法出現(xiàn)的。而當(dāng)元素滾動到達(dá)頂部或底部的時(shí)候,輸出的是就有'd'了,但是這個時(shí)候并沒有輸出'b',說明scroll事件本來就沒有發(fā)生冒泡。而document的scroll事件是由于其他因素觸發(fā)的。
2.在element的mousewheel事件處理里把冒泡取消
e.stopPropagation();
這時(shí)候在元素內(nèi)滾動鼠標(biāo)滾輪,'c'始終是無法出現(xiàn)的,說明我們阻止mousewheel事件的冒泡成功了。但是在滾動條到達(dá)底部或頂部時(shí),雖然'c'依舊沒有出現(xiàn),但是'd'卻出現(xiàn)了,說明這個時(shí)候的document的scroll事件是靠element的mousewheel來觸發(fā)的。
到這里就出現(xiàn)一個問題:element的mousewheel事件在默認(rèn)處理里對這一情形進(jìn)行了處理嗎?
3.在element的mousewheel事件處理里取消默認(rèn)處理
e.preventDefault();
這時(shí)候在元素內(nèi)滾動鼠標(biāo),只會有'a'、'c'會出現(xiàn),頁面也不會滾動。說明鼠標(biāo)滾輪滾動element頁面的效果是由element的mousewheel默認(rèn)事件處理來的。這個時(shí)候留意實(shí)驗(yàn)1中滾輪滾動一下'b'的輸出數(shù)量,大概就能猜到默認(rèn)處理的過程。
4.在element的mousewheel里添加一個自己的頁面滾動(與默認(rèn)處理的滾動方向相反)
element.scrollTop+=e.wheelDelta>0?30:-30;//手動添加的頁面滾動
這個時(shí)候在元素內(nèi)滾動鼠標(biāo),你會發(fā)現(xiàn)即使?jié)L動到頂部或底部,元素外的頁面并不會滾動,且并沒有輸出'd',也就是document的scroll事件沒有觸發(fā)。不好的一點(diǎn)是你在滾動到底部或頂部時(shí),繼續(xù)滾動鼠標(biāo)的話,元素內(nèi)還是會滾動,只不過是先下再上(或先上再下)地波動一下。
5.在element的mousewheel里添加一個自己的頁面滾動(與默認(rèn)處理的滾動方向相同)
element.scrollTop+=e.wheelDelta<0?30:-30;//手動添加的頁面滾動
這個時(shí)候在元素內(nèi)滾動鼠標(biāo),你會發(fā)現(xiàn)即使?jié)L動到頂部或底部,元素外的頁面跟著滾動,且輸出'd',也就是document的scroll事件觸發(fā)了。
這里需要注意到一點(diǎn):元素的scrollTop屬性是無法無限增加和減少的,到了滾動的頂部或底部后只能反向變化(可以自行輸出測試)。
6.在實(shí)驗(yàn)5的基礎(chǔ)上,將滾動的距離調(diào)整到很大
element.scrollTop+=e.wheelDelta<0?300:-300;(值要大等于滾動行程)
認(rèn)真觀察輸出的'b'的個數(shù),和實(shí)驗(yàn)1的對比,你會發(fā)現(xiàn)這次只有1個'b',而且還輸出了'd',而且'd'的數(shù)量還不少。經(jīng)過一些其他的實(shí)驗(yàn),得到:默認(rèn)事件處理里的判斷大概如下:
(function scroll(element){ for(var i=0;i<12;i++){ var temp=element.scrollTop; element.scrollTop+=e.wheelDelta<0?10:-10; //滾動算法肯定不是這個,這里只是簡單演示 if(temp!= element.scrollTop){ //滾動‘消息樹'的下一個元素(和冒泡是一個列表) var newEle=....//消息樹怎么獲取我不懂 scroll(newEle); return; } } })();
驗(yàn)證例子:
addEventListener(element,'mousewheel',function(e){ console.log('a'); }); addEventListener(element,'scroll',function(e){ console.log('b'); }); addEventListener(document.documentElement,'mousewheel',function(e){ console.log('c'); }); addEventListener(document,'scroll',function(e){ console.log('d'); });
結(jié)論:通過上面的6個實(shí)驗(yàn),很容易發(fā)現(xiàn)在元素的mousewheel的默認(rèn)處理事件里對scrollTop屬性進(jìn)行變化和判斷,如果沒有發(fā)生變化就對外部元素進(jìn)行滾動一下(具體滾動算法不懂,滾動距離和鼠標(biāo)滾一下是一樣的),以此類推,如果下一個元素到邊界了,就再下一個。而這個過程和冒泡是沒有關(guān)系的,只是當(dāng)前元素的mousewheel默認(rèn)事件處理進(jìn)行的。
應(yīng)用:因此為了實(shí)現(xiàn)元素滾動到底時(shí)繼續(xù)滾動卻不會使外部元素滾動,我們可以直接取消它的默認(rèn)處理,然后給一個自己的滾動函數(shù)就可以了。至于怎么滾就看自己給什么函數(shù)了,而冒泡取不取消也看自己,上面的默認(rèn)處理在冒泡和捕獲階段是不進(jìn)行的。
例子如下:
addEventListener(element,'mousewheel',function(e){ console.log('a'); e.preventDefault(); // e.stopPropagation(); ulObj.scrollTop+=e.wheelDelta<0?20:-20; }); addEventListener(element,'scroll',function(e){ console.log('b'); }); addEventListener(document.documentElement,'mousewheel',function(e){ console.log('c'); }); addEventListener(document,'scroll',function(e){ console.log('d'); });
看完了這篇文章,相信你對“vue中引入mousewheel事件及兼容性處理方式的示例分析”有了一定的了解,如果想了解更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。