移動端Vue2.x Picker的全局調(diào)用實現(xiàn)
什么是Picker組件
對標(biāo)PC端的Select標(biāo)簽, 移動端的選擇框一般是在viewPort底部彈出

Picker組件存在的問題
- Picker通常以fixed布局,但是我們在寫Picker組件時有遇到過該組件無法在viewport的底部彈出,而是在組件內(nèi)部彈出,導(dǎo)致樣式混淆,不符合C端審美,造成以上問題的原因是因為[層疊上下文]的原因,fixed布局并不是基于viewport為底板,而是當(dāng)前的層疊上下文
- Picker若是放置在根組件下的話會造成數(shù)據(jù)流流向出現(xiàn)混淆,嵌套過深層級的組件無法很便利的觸發(fā)Picker的顯示與隱藏,需要結(jié)合狀態(tài)管理vuex來做處理或者通過透傳$listeners,這在一定程度上增加了開發(fā)者的心智負(fù)擔(dān)
解決思路
利用聲明式編程將Picker放置在Body下去使用, 可以較好的規(guī)避以上的兩個問題,例如利用以下方式調(diào)用picker的顯示與隱藏
this.$picker(組件選項, {
wrapper: {
props: {},
on: {}
},
props: {},
on: {}
})
選項解釋
- wrapper: picker函數(shù)編程參數(shù)
- props: 組件選項的選項配置
- on: 組件選項的時間綁定
解決方案
目錄劃分
- Components
- BaseUsedComponents
- Picker
- Picker.vue
- index.js
- main.js
描繪Picker容器
Picker.vue文件作用:
- 繪制Picker容器
- 利用transition內(nèi)置組件結(jié)合css3的animation做動畫過渡
代碼如下:
<transition name="slideup"> <div class="picker" v-if="show"> <slot></slot> <div class="mask"></div> </div> </transition>
創(chuàng)建Picker
思路大綱
- 定義一個Picker函數(shù), 該函數(shù)需要做以下幾點:
- 生成Picker的實例PickerInstance
- 將PickerInstance.show置為true
- 將Picker容器放入到body底部
- Picker組件生成需要使用防抖措施,不能在連續(xù)點擊下
- 將傳入的組件選項根據(jù)props與on屬性生成vnode,并且放置到默認(rèn)插槽內(nèi)
- 點擊mask元素會將Picker隱藏,這里需要再定義一個hide方法
- hide方法需要做以下幾個問題
- 將實例下show屬性置為false
- 刪除body下的安插Picker容器
- 將實例置為Null,調(diào)用GC
Picker函數(shù)

- 調(diào)用create函數(shù)生成Picker實例
- 判斷實例是否存在
- 保留當(dāng)前組件選項以及配置
- 更改Picker組件的show屬性彈出彈窗,并且安插到body下
create
- 創(chuàng)建一個el作為Picker的容器,安插到body下
- 在render函數(shù)里,Picker將之前傳入的組件選項作為默認(rèn)插槽放置到內(nèi)部,并且自身作為當(dāng)前實例的子組件充當(dāng)根元素
- mounted函數(shù)里獲取對應(yīng)的transition時間作為之后hide時觸發(fā)實際

為什么需要在requestAnimationFrame里去取動畫時間, 而不是在mounted直接可以獲取?
組件的mounted函數(shù)是在初始化渲染后就會調(diào)用,而Toast組件通過設(shè)置showStatus去觸發(fā)transition的enter函數(shù)(雖然Toast組件mounted在之前就會被調(diào)用,但此時toast dom上不存在transition class),此時由于觸發(fā)的是data.setter函數(shù),從而對Watcher進(jìn)行派發(fā)更新,導(dǎo)致所有的操作都在nextTick(也就是微任務(wù))里執(zhí)行, 所以調(diào)用順序是這樣的:
Toast組件Mounted -> 父組件Mounted(也就是現(xiàn)在所處的Mounted函數(shù), 注意此時因為toast里的transition沒有攜帶appear屬性,導(dǎo)致transition enter函數(shù)不會觸發(fā),從而transition class不會被添加) -> nextTick() -> Toast組件update(v-show) -> transition(v-show觸發(fā)enter函數(shù)) -> toast dom增加了transition類名 -> window.getComputedStyle(toast)獲取toastDuration,我們也可以在nextTick里獲取,介于transition active在動畫全過程都會有,并且requestAnimationFrame屬于瀏覽器重繪(painter)鉤子函數(shù),比微任務(wù)還要靠后執(zhí)行,所以在這里獲取
show
- 獲取Picker的實例,Picker是作為該實例的根元素
- 標(biāo)記Mounted屬性,表示已經(jīng)安插
- 監(jiān)聽show屬性,在show置為false時調(diào)用hide函數(shù)
- 安插到body下

hide
- 重置Mounted屬性為false
- 將show函數(shù)里的定義的teardown監(jiān)聽函數(shù)刪除掉,釋放內(nèi)存
- 設(shè)置延時器作為刪除真實DOM的鉤子函數(shù)

為什么采用setTimeout去刪除
使用監(jiān)聽transtionend會有一個問題:
Vue本身在transition組件子節(jié)點里監(jiān)聽了transitionend(或者animationend)
動畫完成后就會刪除掉transition class, 那么此時transition-property就會消失掉
根據(jù)文檔顯示, transition-property消失后將不觸發(fā)transition鉤子函數(shù),繼而無法觸發(fā)
transitionend函數(shù),導(dǎo)致remove可能會無法調(diào)用,留下之前的ToastConainer
remove
remove函數(shù)作用是刪除真實DOM、清除延時器、將timer以及Picker實例置為null, 調(diào)用GC

updateChildrenComponent
Picker組件完成后,發(fā)現(xiàn)更改傳入組件的里的props沒有重新,所以這里寫了一個手動觸發(fā)更新組件的函數(shù),組件vnode有4個鉤子函數(shù),prepatch是做為update時調(diào)用,值有兩個,第一個是上一次的vnode,而第二個就是更改后的vnode,所以我們在PickerCommand函數(shù)里預(yù)暫了原先vnode以及Component,做為diff的舊vnode,調(diào)用此函數(shù)既可以更新組件

結(jié)束語
Picker組件只是一個例子,還可以使用更多方法去實現(xiàn)。到此這篇關(guān)于移動端Vue2.x Picker的全局調(diào)用實現(xiàn)的文章就介紹到這了,更多相關(guān)Vue2.x Picker全局調(diào)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue中keep-alive 實現(xiàn)后退不刷新并保持滾動位置
這篇文章主要介紹了Vue中keep-alive 實現(xiàn)后退不刷新并保持滾動位置的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03
Vuex進(jìn)行Echarts數(shù)據(jù)頁面初始化后如何更新dom
這篇文章主要為大家詳細(xì)介紹了使用Vuex做Echarts數(shù)據(jù)時,當(dāng)頁面初始化后如何更新dom,文中的示例代碼講解詳細(xì),有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11
el-input寬度跟隨輸入內(nèi)容自適應(yīng)的實現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于el-input寬度跟隨輸入內(nèi)容自適應(yīng)的實現(xiàn)方法,我們再實際應(yīng)用中可能需要input文本框能夠根據(jù)輸入字符的所占據(jù)的寬度自動調(diào)節(jié)尺寸,需要的朋友可以參考下2023-08-08
Vue-router 報錯NavigationDuplicated的解決方法
這篇文章主要介紹了Vue-router 報錯NavigationDuplicated的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
elementui源碼學(xué)習(xí)之仿寫一個el-divider組件
這篇文章主要為大家介紹了elementui源碼學(xué)習(xí)之仿寫一個el-divider組件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08

