背景
平常做前端開發(fā)的應(yīng)該知道,在前端組件中,有兩種組件
-
一種是針對移動端的組件
-
另一種是針對pc的組件
? 而pc的組件主要是對鼠標,鍵盤等操作的支持,而移動端組件常用的事件是觸摸等事件
? 這時,狗血的就來了,業(yè)務(wù)總是能用各種奇怪的想法讓你來回串著開發(fā)
? 我們有一款web是寫在企業(yè)微信內(nèi)部的h5網(wǎng)頁,他使用的是移動端組件,但是這個應(yīng)用由于企業(yè)微信手機端和電腦端都有,導致了業(yè)務(wù)也會用電腦操作的需求
? 這天,他說選項組件為什么不能使用滾輪選擇?而是只能使用拖拽?這樣不好用,要改成也支持滾輪
解決路徑
嫌麻煩,請直接跳到最后的解決方案,前面只是解決路程
vant組件庫
? 首先咱們就去看這個組件,也就是 vant官方庫,他有一個能夠兼容桌面的
? 這咱們一看就來勁兒了呀,正好咱們要用鼠標滾輪,肯定能夠?qū)崿F(xiàn)鼠標滾輪模擬拖拽呀,咱們繼續(xù)往下看下去
? 然后發(fā)現(xiàn)本地項目中已經(jīng)安了這個插件,但是滾輪效果仍然不生效,于是乎,這種方法不可以
gihtub issues
? 當然,如果咱們只會查文檔解決問題那么咱們就不是合格的程序員了,咱們也要學會去源碼項目的issues,于是咱們?nèi)タ聪聉ant項目源碼
? 看到關(guān)于滾輪的有19個已解決,咱們就開心了,看來前人已經(jīng)把路子探好了,咱們直接copy就行了
? 然后看到開發(fā)大大的回答就哭了,沒計劃支持,以后也不會支持,
CSDN
? csdn回答 這種方法也時候也能解決一些問題,但是他通過改node_modules解決的,這種方法涉及到如何把源碼包抽離出來,進行更改,然后所有的引入源也更改,比較麻煩,而且害怕涉及到線上問題
hammerjs
? 再后來就想著使用hammerjs模擬手指操作可以么?滾輪滾一個,然后模擬手指滑動多少距離,這樣就不用麻煩判斷邊界問題和選中問題,但是通過引入hammerjs問題頻頻。例如獲取dom的麻煩等等問題,并且無法監(jiān)聽你是否能夠監(jiān)聽你是否模擬成功了,所以這種也不行
換組件?。?/h4>
? 換組件的話意味著重寫,開發(fā)周期起碼兩天以上,這種特別麻煩
? 我嘗試使用
- Mint UI
- Cube UI
- Vux
- MUI
等等,但是都沒發(fā)現(xiàn),突然我想看看antd-mobile,哭了,發(fā)現(xiàn)他有,但是他是react組件,vue和react串著寫,肯定不可能呀
chatGPT(解決方案1)
改組件
? 其實上面換組件,和使用hammerjs都是他給我推薦的,可能是關(guān)鍵詞不行?后來一個解決方法不用換組件,可以在原生寫
原回答如下
-
在
mounted
鉤子函數(shù)中,獲取到 Picker 組件的 DOM 元素,并添加wheel
事件監(jiān)聽函數(shù)。 -
在
wheel
事件監(jiān)聽函數(shù)中,根據(jù)鼠標滾輪滾動的方向來修改 Picker 組件的選中值。可以通過調(diào)用scrollToOption
方法來實現(xiàn)滾動選中值的效果。
<template>
<div>
<van-picker
ref="picker"
:columns="columns"
@change="handleChange"
:default-index="currentIndex"
/>
</div>
</template>
<script>
// 如果不是v2記得把 :default-index="currentIndex"屬性刪掉,雖然我也不知道會出現(xiàn)什么錯誤
import { Picker } from 'vant';
export default {
components: {
[VanPicker.name]: Picker,
},
data() {
return {
columns: ['A', 'B', 'C', 'D', 'E'],
currentIndex: 0
};
},
mounted() {
//獲取到picker的dom
//如果咱們在pouop里面寫的話,就應(yīng)該寫到當彈窗出來再獲取dom,否則獲取不出來
const pickerEl = this.$refs.picker.$el;
pickerEl.addEventListener('wheel', this.handleWheel);
},
methods: {
handleChange(value, index) {
this.currentIndex = index;
console.log('Selected value(value, index)', value, index);
},
handleWheel(event) {
event.preventDefault();
//Math.sign()函數(shù),返回+/-1,表示正數(shù)還是負數(shù),例如deltaY發(fā)現(xiàn)是-100,那么Math.sign返回也是-1,但是傳入0那就是0
const delta = Math.sign(event.deltaY);
//獲取最大下標
const maxIndex = this.columns.length - 1;
//計算當前下標,因為滾輪和拖拽是相反的邏輯,我們可以試下,觸控板和鼠標滾輪就是相反的,所以要減
const newIndex = this.currentIndex - delta;
//邊界處理
if (newIndex >= 0 && newIndex <= maxIndex) {
this.currentIndex = newIndex;
//動畫可能不流暢
//vant 4的話
this.$refs.picker.scrollToOption(newIndex);
//vant3 this.$refs.picker.scrollToOption(newIndex);
//vant2 的解決方案,我是以下的解決方法解決的
//這個是控制動畫的時長
// this.$refs.picker.$el.getElementsByClassName('van-picker-column__wrapper')[0].style.transitionDuration='800ms'
//這個是給哪個變化添加屬性,由于省事就添加all
//this.$refs.picker.$el.getElementsByClassName('van-picker-column__wrapper')[0].style.transitionProperty='all'
}
}
},
};
</script>
? 在這個示例中,我們在 mounted
鉤子函數(shù)中獲取到了 Picker 組件的 DOM 元素,并添加了 wheel
事件監(jiān)聽函數(shù)。在 handleWheel
方法中,我們根據(jù)鼠標滾輪滾動的方向來修改 Picker 組件的選中值,并調(diào)用 scrollToOption
方法來實現(xiàn)滾動選中值的效果。最后,我們在 handleChange
方法中輸出了選中的值和索引。
需要注意的是,在 handleWheel
方法中,我們調(diào)用了 event.preventDefault()
來阻止瀏覽器默認的滾動行為,以避免與 Picker 組件的滾動效果沖突。
如何全局生效?
使用混入,以下是全部代碼,我的vant是2版本
// mixins.js 文件
//1.picker組件需要添加ref
//2.騙
export const myMixin = {
methods: {
//這個事件放到picker彈出的地方
/***
* picker滾動事件
* @param picker picker的ref
* @param cloum picker的數(shù)據(jù)
* @param getCurFn 默認選中的index,是一個函數(shù),因為需要拿到實時的
* @param setIndex 設(shè)置index的方法
* @returns {Promise<void>}
*/
async getpicker(picker,cloum,getCurFn,setIndex){
await new Promise(resolve => {setTimeout(resolve,100)})
const pickerEl = this.$refs[picker].$el;
pickerEl.addEventListener('wheel', (event)=>this.handleWheel(event,picker,cloum,getCurFn,setIndex));
// console.log("pickerEl",pickerEl)
},
handleWheel(event,picker,cloum,getCurFn,setIndex) {
// debugger
event.preventDefault();
const delta = Math.sign(event.deltaY);
// debugger
const maxIndex = cloum.length - 1;
const newIndex = getCurFn() + delta;
// debugger
this.$refs[picker].$el.getElementsByClassName('van-picker-column__wrapper')[0].style.transitionDuration='800ms'
this.$refs[picker].$el.getElementsByClassName('van-picker-column__wrapper')[0].style.transitionProperty='all'
if (newIndex >= 0 && newIndex <= maxIndex) {
// this.popupData.defaultIndex = newIndex;
// console.log(" setIndex", setIndex,newIndex)
setIndex(newIndex)
}
},
}
};
調(diào)用(需要再全部引用的地方都調(diào)用)
this.getpicker('picker',this.popupData.comSurList,()=>this.popupData.defaultIndex,(index)=>this.popupData.defaultIndex=index)
我們能夠看到他的缺點了,需要再所有的地方都去調(diào)用一次
依賴包打補丁(最終解決,最簡單)
更新vant到最新版本
? 更新vant之后,我們可以發(fā)現(xiàn)vant的picker組件已經(jīng)支持滾動滑輪了,但是每個滑輪滑動的過大,可能一次跳過兩個選項,我們要進行修改
改源碼
? 改源碼的方式有以下幾種
-
提issues等待作者更新(莫不是在開玩笑)
-
將源碼粘貼到component文件,然后全局改引用的位置(有一點點麻煩,項目也會變大,也有通過在webpack添加alis添加別名直接全局修改引用)
-
將源碼倉庫fork到自己的倉庫,然后修改源碼后,然后在自己項目中的npm修改一下包的位置后面的rep改成自己倉庫的地址(但是記住千萬別刪這個倉庫,否則以后你的項目就啟不起來了)
-
通過patch-package對源碼包打補丁
可以先了解一下patch-package 的介紹
說白了就三步
- 裝依賴
- 直接改源碼
- 執(zhí)行命令將改的源碼變成diff文件
- packagejson添加鉤子執(zhí)行
安裝一下patch package
npm i patch-package
yarn add patch-package postinstall-postinstall
改源碼
目錄 node_modules->vant->picker->PickerColumn.js
在node_modules中找到vant(注意不是@vant,那個可能是vant的一些補丁包)
可以看到他的以下結(jié)構(gòu)
全局搜索一下wheel,找到onMouseWheel的方法,可以除以一個倍數(shù),讓其流暢
編譯補丁
npx patch-package package-name
此時我們可以看到根目錄已經(jīng)添加了一個patches文件了,查看文件發(fā)現(xiàn)是我們修改的相關(guān)位置
添加鉤子
默認會在packagejson中scripts添加一個鉤子函數(shù)
"postinstall": "patch-package",
他的意思是安裝依賴的時候立馬支持patch-package打補丁
此時就可以測試一下,將node_modules刪除后測試一下是否成功了
異常解決
pm WARN lifecycle xxx.xxx.com@0.1.0~postinstall: cannot run in wd xxx.xxx.com@0.1.0 patch-package (wd=/node)
我們部署線上的時候可能會出問題,因為有的docker安裝依賴的時候工作目錄可能不一致,可以嘗試將鉤子函數(shù)添加一個打包前執(zhí)行,此時就會正常執(zhí)行了
"prebuild": "patch-package",
由于項目可能需要有不同環(huán)境的打包命令,所以可以以下
文章來源:http://www.zghlxwxcb.cn/news/detail-792764.html
//開發(fā)環(huán)境需要
"postinstall": "patch-package",
//打包需要
"prebuild": "patch-package",
"prebuild:test": "patch-package",
"prebuild:feature1": "patch-package",
"prebuild:feature2": "patch-package",
"prebuild:prod": "patch-package"
于此,這項目就可以告別一段落文章來源地址http://www.zghlxwxcb.cn/news/detail-792764.html
到了這里,關(guān)于vant選擇器組件添加鼠標滾輪(多種解決方法包括生產(chǎn)環(huán)境)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!