使用Vue3實(shí)現(xiàn)一個穿梭框效果的示例代碼
效果
當(dāng)選中數(shù)據(jù),并且點(diǎn)擊相對應(yīng)的方向箭頭時,選中的數(shù)據(jù)會發(fā)送到對面,并且數(shù)據(jù)會保持正確的順序進(jìn)行排列。
在線預(yù)覽:https://chenyajun.fun/#/transfer
實(shí)現(xiàn)
左右兩邊邏輯一致,這里只對左側(cè)的進(jìn)行分析
先看一下 html 結(jié)構(gòu) 方便理解
<div class="module-wrapper"> <div class="module-head"> <span>list1</span> <span>{{ currentSelectLeft }}</span> </div> <div class="module-content"> <div v-if="!listLeft.length" style="text-align: center">No data</div> <div class="module-item" v-for="(item, index) in listLeft" @click="handleTransferLeft(index)"> <input style="width: 20px; height: 20px" type="checkbox" :checked="item.checked" /> <span :style="{ color: item.checked ? '#68b2ff' : '#000', }" >{{ item.label }}</span > </div> </div> </div>
數(shù)據(jù)處理
首先初始化 10 條穿梭框數(shù)據(jù),key 屬性用于排序,label 用于展示數(shù)據(jù),最后為數(shù)據(jù)添加 checked 屬性(主要用于標(biāo)記是否被選中),然后將數(shù)據(jù)賦值給左邊的列表 listLeft。
function getListData() { let data = [] for (let index = 1; index <= 10; index++) { data.push({ key: index, label: 'option' + index, }) } //對data進(jìn)行處理 默認(rèn)我們認(rèn)為沒有checked屬性 data.forEach((item) => { item.checked = false }) listLeft.value = data }
點(diǎn)擊狀態(tài)取反
上面我們初始化了數(shù)據(jù),下面需要做的是當(dāng)點(diǎn)擊每一項(xiàng) option 的時候讓狀態(tài)取反。
點(diǎn)擊 option 時只需把相應(yīng)的 index 傳入,然后進(jìn)行取反操作即可。
// 點(diǎn)擊進(jìn)行狀態(tài)取反 function handleTransferLeft(currentIndex) { listLeft.value[currentIndex].checked = !listLeft.value[currentIndex].checked }
比例狀態(tài)
我們看到了上面的已選數(shù)據(jù)和總數(shù)據(jù)的比例狀態(tài)
先拿到已選數(shù)據(jù)
// 左側(cè)checked的數(shù)據(jù) const currentCheckedLeft = computed(() => { return listLeft.value.filter((item) => item.checked) })
將左側(cè)選中數(shù)據(jù)的長度 比上 數(shù)據(jù)總長度即可
點(diǎn)擊箭頭進(jìn)行穿梭
// 點(diǎn)擊右箭頭 function toRight() { // 對選中數(shù)據(jù)進(jìn)行深拷貝 const deepCloneData = JSON.parse(JSON.stringify(currentCheckedLeft.value)) // 把剛選擇的數(shù)據(jù)狀態(tài)進(jìn)行清除 deepCloneData.forEach((item) => { item.checked = false }) // 把選中的數(shù)據(jù)添加到右邊 需要把剛選擇的數(shù)據(jù)狀態(tài)進(jìn)行清除 listRight.value.push(...deepCloneData) // 對右邊數(shù)據(jù)進(jìn)行重新排序 listRight.value.sort((a, b) => a.key - b.key) // 找到未選中數(shù)據(jù) 進(jìn)行重新賦值 const noCheckedLeftData = listLeft.value.filter((item) => !item.checked) listLeft.value = noCheckedLeftData }
先對選中數(shù)據(jù)清除狀態(tài),因?yàn)槿绻磺宄隣顟B(tài)可能會導(dǎo)致穿梭過的的數(shù)據(jù)仍然還是選中。
如圖所示:1,2是剛穿梭過去的數(shù)據(jù),仍保留狀態(tài)
注意需要對選中數(shù)據(jù)進(jìn)行深拷貝,因?yàn)橄旅嫘枰玫轿催x中的數(shù)據(jù),如果不進(jìn)行深拷貝,那下面再去篩選未選中的數(shù)據(jù)時就會把所有的數(shù)據(jù)選中。
// 對選中數(shù)據(jù)進(jìn)行深拷貝 const deepCloneData = JSON.parse(JSON.stringify(currentCheckedLeft.value)) // 把剛選擇的數(shù)據(jù)狀態(tài)進(jìn)行清除 deepCloneData.forEach((item) => { item.checked = false })
接下來篩選出來選中數(shù)據(jù)后,將數(shù)據(jù)添加到右邊的數(shù)組
// 把選中的數(shù)據(jù)添加到右邊 需要把剛選擇的數(shù)據(jù)狀態(tài)進(jìn)行清除 listRight.value.push(...deepCloneData)
然后再對右邊的數(shù)組進(jìn)行排序
// 對右邊數(shù)據(jù)進(jìn)行重新排序 listRight.value.sort((a, b) => a.key - b.key)
現(xiàn)在已經(jīng)將數(shù)據(jù)穿梭到右側(cè),那怎么去除左側(cè)已穿梭的數(shù)據(jù)呢?
篩選出來左邊未選擇的數(shù)據(jù),重新賦值給左邊數(shù)組即可
// 找到未選中數(shù)據(jù) 進(jìn)行重新賦值 const noCheckedLeftData = listLeft.value.filter((item) => !item.checked) listLeft.value = noCheckedLeftData
這一步也是上面為什么深拷貝的原因。
如果不進(jìn)行深拷貝,如圖所示:
已經(jīng)穿梭了過去,但是取未篩選數(shù)據(jù)時,因?yàn)樯厦娴臓顟B(tài)已經(jīng)取反,這里都會選擇到。
總結(jié)
我們需要知道如果要實(shí)現(xiàn)一個穿梭框效果,我們大概都需要做哪些東西呢?
那首先是對左側(cè)的初始化數(shù)據(jù),我們需要對數(shù)據(jù)進(jìn)行加工,添加 checked 屬性,方便后面進(jìn)行篩選。
其次是我們找出我們選中的數(shù)據(jù),添加到右側(cè),同時把左側(cè)選中的數(shù)據(jù)進(jìn)行移除。
源碼
GitHub:https://github.com/chenyajun-create/transfer
以上就是使用Vue3實(shí)現(xiàn)一個穿梭框效果的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Vue3實(shí)現(xiàn)穿梭框的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue使用v-viewer插件實(shí)現(xiàn)圖片預(yù)覽和縮放和旋轉(zhuǎn)等功能(推薦)
v-viewer是一個基于viewerjs封裝的vue圖片預(yù)覽組件,有預(yù)覽縮放拉伸旋轉(zhuǎn)切換拖拽等功能,支持配置化,這篇文章主要介紹了Vue使用v-viewer插件實(shí)現(xiàn)圖片預(yù)覽和縮放和旋轉(zhuǎn)等功能,需要的朋友可以參考下2023-02-02Vue使用mounted和created時,this無法指向data中的數(shù)據(jù)問題
這篇文章主要介紹了Vue使用mounted和created時,this無法指向data中的數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07Vue單文件組件開發(fā)實(shí)現(xiàn)過程詳解
這篇文章主要介紹了Vue單文件組件開發(fā)實(shí)現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07vue 監(jiān)聽input輸入事件(oninput)的示例代碼支持模糊查詢
這篇文章主要介紹了vue 監(jiān)聽input輸入事件(oninput)支持模糊查詢,比如說表格模糊查詢,實(shí)現(xiàn)一邊輸入,一邊過濾數(shù)據(jù),本文通過示例代碼給大家詳細(xì)講解,需要的朋友可以參考下2023-02-02vue中數(shù)據(jù)不響應(yīng)的問題及解決
這篇文章主要介紹了vue中數(shù)據(jù)不響應(yīng)的問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09vue項(xiàng)目中如何將當(dāng)前頁面生成圖片
這篇文章主要介紹了vue項(xiàng)目中如何將當(dāng)前頁面生成圖片問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10vue項(xiàng)目頁面的打印和下載PDF加loading效果的實(shí)現(xiàn)(加水印)
這篇文章主要介紹了vue項(xiàng)目頁面的打印和下載PDF加loading效果的實(shí)現(xiàn)(加水印),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12vue3.0如何使用computed來獲取vuex里數(shù)據(jù)
這篇文章主要介紹了vue3.0如何使用computed來獲取vuex里數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04