這篇文章主要為大家展示了“Element-ui中元素滾動時el-option超出元素區(qū)域的問題”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Element-ui中元素滾動時el-option超出元素區(qū)域的問題”這篇文章吧。
網(wǎng)站建設(shè)公司,為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁設(shè)計及定制網(wǎng)站建設(shè)服務(wù),專注于成都定制網(wǎng)站,高端網(wǎng)頁制作,對成都混凝土攪拌罐車等多個行業(yè)擁有豐富的網(wǎng)站建設(shè)經(jīng)驗的網(wǎng)站建設(shè)公司。專業(yè)網(wǎng)站設(shè)計,網(wǎng)站優(yōu)化推廣哪家好,專業(yè)seo優(yōu)化優(yōu)化,H5建站,響應(yīng)式網(wǎng)站。復(fù)現(xiàn)場景, 看圖
分析原因
為簡單起見, 把選項區(qū)域描述為popperEl
popperEl的z-index 比較大, 會覆蓋在其他元素上面
popperEl默認是插入body元素的(可以將popper-append-to-body設(shè)為false后不插入到body)
popperEl是在mouseup事件里去做隱藏邏輯的, 而按下鼠標(biāo), 移動滾動條的時候, 并沒有觸發(fā)mouseup事件.
popperEl并沒有監(jiān)聽滾動事件(沒法監(jiān)聽, 也沒必要監(jiān)聽)
解決方案
方案一
我最初想到的解決方案是通過css解決,通過popper-class屬性給Select下拉框添加類名,然后用css來做, 試了一下這個方案并不可行(只能在某些特定的場景下起作用),遂放棄,可能最優(yōu)雅最高性能的方法就是用css來搞定, 有踩過這個坑的朋友請指點一下
方案二
通過監(jiān)聽$root的scroll事件,利用事件冒泡,只需要在根元素上添加scroll事件的監(jiān)聽就可以了, 測試一番之后, 發(fā)現(xiàn)scroll事件根本不支持冒泡, event.bubbles為false)。
方案三
通過查看element-ui 的select.vue, 發(fā)現(xiàn)控制popperEl顯隱的是visible 和 emptyText這兩個實例屬性, 很明顯, emptytext是不能動的, 只能在visible上動手腳了. 這里放一小段源碼
0 && !loading"> {{ emptyText }}
全局搜索this.visible, 發(fā)現(xiàn)了這個方法
handleClose() { this.visible = false; },
這下好辦了, 按圖索驥, 順藤摸瓜, 找到這個
后面的省略...找到v-clickoutside指令之后, 豁然開朗 原來點擊其他區(qū)域的時候, popperEl會自動關(guān)閉的奧秘在這里, 結(jié)合方案二的靈感, 現(xiàn)給出如下代碼.
// src/mixins/fackClickOutSide.js let lock = true; let el = null; const MousedownEvent = new Event('mousedown', {bubbles:true}); const MouseupEvent = new Event('mouseup', {bubbles:true}); const fakeClickOutSide = () => { document.dispatchEvent(MousedownEvent); document.dispatchEvent(MouseupEvent); lock = true; // console.log('dispatchEvent'); }; const mousedownHandle = e => { let classList = e.target.classList; if(classList.contains('el-select__caret') || classList.contains('el-input__inner')) { lock = false; return; } if(lock) return; fakeClickOutSide(); }; const mousewheelHandle = e => { if(lock || e.target.classList.contains('el-select-dropdown__item') || e.target.parentNode.classList.contains('el-select-dropdown__item')) return; fakeClickOutSide(); }; const eventListener = (type) => { el[type + 'EventListener']('mousedown', mousedownHandle); window[type + 'EventListener']('mousewheel', mousewheelHandle); window[type + 'EventListener']('DOMMouseScroll', mousewheelHandle); // fireFox 3.5+ } export default { mounted() { el = this.$root.$el; el.addFakeClickOutSideEventCount = el.addFakeClickOutSideEventCount || 0; (! el.addFakeClickOutSideEventCount) && this.$nextTick(() => { eventListener('add'); }); el.addFakeClickOutSideEventCount += 1; }, destroyed() { eventListener('remove'); el.addFakeClickOutSideEventCount -= 1; }, }使用姿勢
建議在根組件上混合進去, 當(dāng)然,你也可以在需要的組件上去混合(不太建議, 這點代碼性能損耗應(yīng)該不大吧, 哈哈哈)
// src/App.vue import fakeClickOutSide from '@/mixins/fakeClickOutSide.js' export default { name: 'App', mixins: [fakeClickOutSide], }測試
常規(guī)基礎(chǔ)用法 和 自定義模板用法(模板內(nèi)沒有嵌套的標(biāo)簽) 均完美通過.
自定義模板內(nèi)如果嵌套多級標(biāo)簽, 需要在標(biāo)簽上添加標(biāo)記,然后在mousewheel事件回調(diào)里判斷是否有這個標(biāo)記.
總結(jié)
依然存在的問題(隱患):
在mousewheel事件回調(diào)沒有做節(jié)流, 考慮到有鎖, 且滾輪事件觸發(fā)的頻率也不是很高(相對于mousemove事件來講), 性能消耗并不大, 遂不做節(jié)流(主要是懶).
在mousewheel事件回調(diào)里,判斷event.target 是否是在popperEl元素內(nèi)部的方法感覺不是很靠譜, 且效率不高, 在mousedown 事件里判斷是不是el-select元素的方法也存在同樣的隱患, 后期再想辦法修改(修改是不可能修改的, 又不是不能用).
在自定義模板用法里, 如果有嵌套的標(biāo)簽, 那么在mousewheel事件回調(diào)里判斷event.target 是不是在popperEl元素內(nèi)部的方法就崩潰了(這是個雷), 目前的解決辦法是手動在嵌套的標(biāo)簽上都加上一個標(biāo)記, 在事件里,添加這個標(biāo)記的判斷, 但是這種做法對于已經(jīng)編寫完成的模板無效, 只能再次修改, 考慮過使用遞歸向上查找, 但是效率不高, 性能消耗太大, 且自定義el-option模板這種情況在我們現(xiàn)階段的業(yè)務(wù)中幾乎不存在, 所以就沒有考慮這個bug.
以上是“Element-ui中元素滾動時el-option超出元素區(qū)域的問題”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
分享標(biāo)題:Element-ui中元素滾動時el-option超出元素區(qū)域的問題-創(chuàng)新互聯(lián)
文章鏈接:http://weahome.cn/article/dgiipe.html