場景
要實現的效果如下
這里用到了ElemrntUI的Transfer穿梭框控件
官方示例代碼
<template> <p style="text-align: center; margin: 0 0 20px">使用 render-content 自定義數據項</p> <div style="text-align: center"> <el-transfer style="text-align: left; display: inline-block" v-model="value" filterable :left-default-checked="[2, 3]" :right-default-checked="[1]" :render-content="renderFunc" :titles="['Source', 'Target']" :button-texts="['到左邊', '到右邊']" :format="{ noChecked: '${total}', hasChecked: '${checked}/${total}' }" @change="handleChange" :data="data"> <el-button class="transfer-footer" slot="left-footer" size="small">操作</el-button> <el-button class="transfer-footer" slot="right-footer" size="small">操作</el-button> </el-transfer> </div> <p style="text-align: center; margin: 50px 0 20px">使用 scoped-slot 自定義數據項</p> <div style="text-align: center"> <el-transfer style="text-align: left; display: inline-block" v-model="value4" filterable :left-default-checked="[2, 3]" :right-default-checked="[1]" :titles="['Source', 'Target']" :button-texts="['到左邊', '到右邊']" :format="{ noChecked: '${total}', hasChecked: '${checked}/${total}' }" @change="handleChange" :data="data"> <span slot-scope="{ option }">{{ option.key }} - {{ option.label }}</span> <el-button class="transfer-footer" slot="left-footer" size="small">操作</el-button> <el-button class="transfer-footer" slot="right-footer" size="small">操作</el-button> </el-transfer> </div> </template> <style> .transfer-footer { margin-left: 20px; padding: 6px 5px; } </style> <script> export default { data() { const generateData = _ => { const data = []; for (let i = 1; i <= 15; i++) { data.push({ key: i, label: `備選項 ${ i }`, disabled: i % 4 === 0 }); } return data; }; return { data: generateData(), value: [1], value4: [1], renderFunc(h, option) { return <span>{ option.key } - { option.label }</span>; } }; }, methods: { handleChange(value, direction, movedKeys) { console.log(value, direction, movedKeys); } } }; </script>
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
關注公眾號
霸道的程序猿
獲取編程相關電子書、教程推送與免費下載。
實現
Transfer 的數據通過 data 屬性傳入。
數據需要是一個對象數組,每個對象有以下屬性:key 為數據的唯一性標識,label 為顯示文本,disabled 表示該項數據是否禁止轉移。
目標列表中的數據項會同步到綁定至 v-model 的變量,值為數據項的 key 所組成的數組。
當然,如果希望在初始狀態時目標列表不為空,可以像本例一樣為 v-model 綁定的變量賦予一個初始值。
就是說賦值需要構建一個對象數組,或者說叫鍵值對數組,每個對象有如下屬性:
key為鍵,即唯一標識
label為值,即顯示文本
比如上面的實現效果,在新增班次組時可以從左邊所有的班次中移動到右邊成為這個班次組所包含的班次,每個班次有班次編號和班次名稱這個兩個屬性。
其中班次編號作為key,班次名稱作為label即顯示文本。
首先在頁面添加一個transfer控件
<el-transfer style="text-align: left; display: inline-block" v-model="form.bhbcvalue" filterable :filter-method="filterMethod" filter-placeholder="請輸入名稱" :titles="['所有班次', '包含班次']" :button-texts="['到左邊', '到右邊']" :format="{ noChecked: '${total}', hasChecked: '${checked}/${total}' }" :data="bcalldata" ></el-transfer>
上面使用了v-model進行數據的雙向綁定,其中form.bhbcvalue是一個對象的數組屬性
// 表單參數 form: { bczbh: undefined, bczmc: undefined, bhbcvalue: [], },
還使用了:filter-method= "filterMethod"
自定義搜索邏輯,其 接收一個方法,當搜索關鍵字變化時,會將當前的關鍵字和每個數據項傳給該方法。
若方法返回 true,則會在搜索結果中顯示對應的數據項。
比如這里的自定義搜索邏輯就是
filterMethod(query, item) { return item.label.indexOf(query) > -1; },
其中query就是關鍵字,item就是每個數據項,我們關鍵字搜索的是根據其顯示的文本搜索,所以取的是item的label屬性。
然后在這些個label數組中查找關鍵字的索引,如果有則會返回大於等於0的索引,如果沒有,則會返回-1。
所以這里的判斷條件是>-1,當結果為true時會顯示對應的數據項。
上面還使用了format列表頂部勾選狀態文案
:format="{ noChecked: '${total}', hasChecked: '${checked}/${total}' }"
它是一個對象有兩個屬性,選中的和沒選中的或者是總共的
格式示例
{ noChecked: '${checked}/${total}', hasChecked: '${checked}/${total}' }
怎樣給Transfer賦值?
通過
:data= "bcalldata"
綁定其數據源,其中bcalldata是一個符合上面規范的鍵值對或者說有指定屬性的對象數組。
首先對此數組進行聲明
data() { return { //所有的班次信息 bcalldata: [],
然后在頁面加載完后執行的created中請求后台獲取數據
created() { //獲取所有班次信息 this.getBcAllData(); },
在獲取數據的方法中
getBcAllData() { getBcAllDataRequest(this.bc).then((response) => { var allbc = response.rows; allbc.forEach((bc, index) => { this.bcalldata.push({ label: bc.bcmc, key: bc.bcbh, }); }); }); },
請求后台獲取對象的list,然后遍歷這里list,獲取其bcbh屬性和bcmc屬性封裝成新對象
並添加進上面的數據源bcalldata數組中。
這樣數據就能顯示在Transfer的左邊框中了。
怎樣獲取選中的數據的?
上面已經通過v-model= "form.bhbcvalue"
將此控件選中的數據即右邊的數據的key即bcbh的數組與form.bhbcvalue進行綁定,就可以取其值來獲取
Transfer控件的值。
怎樣控制它右邊沒有添加值不能點擊新增或者編輯的確定按鈕?
可以使用其change事件來獲取左邊和右邊的數組值,並按照右邊數組的值來獲取有沒有選擇。
change事件在右側元素變化時觸發,回調函數參數(當前值、數據移動的方向('left' / 'right')、發生移動的數據 key 數組)
示例:
<el-transfer style="text-align: left; display: inline-block" v-model="form.bhbcvalue" filterable :filter-method="filterMethod" filter-placeholder="請輸入名稱" :titles="['所有班次', '包含班次']" :button-texts="['到左邊', '到右邊']" :format="{ noChecked: '${total}', hasChecked: '${checked}/${total}' }" @change="handleChange" :data="bcalldata" ></el-transfer>
這里就添加了 @change= "handleChange事件
handleChange(value, direction, movedKeys) { if (direction === "right") { movedKeys.forEach((key) => { let index = this.leftvalue.findIndex((item) => item === key); this.leftvalue.splice(index, 1); }); movedKeys.forEach((key) => { this.rightvalue.push(key); }); } else { movedKeys.forEach((key) => { let index = this.rightvalue.findIndex((item) => item === key); this.rightvalue.splice(index, 1); }); movedKeys.forEach((key) => { this.leftvalue.push(key); }); } console.log(this.leftvalue); console.log(this.rightvalue); },
此事件中value就是當前值,direction是代表方向:right-右邊;left-左邊,movedKeys是代表發生移動的數據 key 數組
在上面事件中首先判斷方向是在右邊的話就遍歷發生移動的數組,將此數組遍歷,
leftvalue是聲明了用來存儲左邊元素的數組,通過對比左邊元素與移動元素相等時,獲取其索引並將它在左邊的數據中移除。
然后將移動的元素添加進右邊的數組。
否則就是移動到左邊,邏輯與移動到右邊相反。
當前存儲左右數組的屬性需要提前聲明
data() { return { bcalldata: [], leftvalue: [], rightvalue: [],
然后在點擊新增或者編輯的確定按鈕時進行判斷
if (this.rightvalue == null || this.rightvalue.length == 0) { this.$alert("請先選擇班次", "提示", { confirmButtonText: "確定", }); } else { addBczgl(this.form).then((response) => { if (response.code === 200) { this.msgSuccess("新增成功"); this.open = false; this.getList(); } }); }
效果如下