antd+vue3 多選框的值為對象數組


 

需求:

  1、自定義多選樣式

  2、多選值為對象數組

  3、已選項側邊顯示,可刪除,並關聯“備選”的選擇狀態

  4、此示例為組件,數據為父組件傳遞而來

難點:多選項的值為對象數組,如果直接使用對象值進行匹配,由於對象的指引不同,所以即使完全相同的值,匹配也不相同。也就導致多選項的值匹配失敗,顯示為空。

思路:

  1、備選:多選框的顯示使用對象數組,值使用id數組匹配

  2、已選:選擇“備選”生成的值為id數組,“已選”根據此id數組匹配“備選”里的所有對象數組生成一個對象數組用以展示

  3、已選:當點擊刪除時,用對象數組里的id匹配id數組,進行刪除,從而改變右側“備選里的值”

 

 

效果圖如下:

 

 

 

主要代碼如下:

 1 <div class="transfer-card-box">
 2     備選:
 3   <div class="transfer-card-body">
 4      <div>
 5          <slot name="search"></slot>
 6      </div>
 7      <div style="height: 86%">
        此處控制全選,checkAll為是否全選的值,indeterminate控制全選的樣式 8 <a-checkbox v-model:checked="checkAll" :indeterminate="indeterminate" 9 @change="onCheckAllChange">全選</a-checkbox> 10 <div class="selector-item-box">
         checkedDataId2為選中的值,此處只記錄id 11 <a-checkbox-group v-model:value="checkedDataId2" >
          optionAll為所有備選的數據,是個對象數組。利用循環柵格實現自定義布局 12 <div v-for="item in optionAll" :key="item.id"> 13 <a-row :gutter="[0,16]"> 14 <a-col :span="24">
              為每一個多選項賦值,值為id 15 <a-checkbox :value="item.id"> 16 {{item.name}} 17 </a-checkbox> 18 </a-col> 19 </a-row> 20 </div> 21 </a-checkbox-group> 22 </div> 23 </div> 24 </div> 25 </div> 26 27 <div class="transfer-card-box"> 28 已選: 29 <div class="transfer-card-body"> 30 <div class="item-flex-between" style="padding-bottom: 4px" 31 v-for="item in checkedData2" :key="item.id"> 32 <div>{{item.name}}</div> 33 <div class="remove-icon" @click="removeItem(item.id)"><CloseCircleOutlined /></div> 34 </div> 35 </div> 36 </div> 37 </div>
 1 import { reactive, toRefs, watch } from 'vue'
 2 
 3 export default {
   父組件傳來的數據
4 props: { 5 optionAll: { type: Array, default() { return [] } },//所有備選項(對象數組) 6 checkedDataId: { type: Array, default() { return [] } },//已選項(id數組) 7 }, 8 setup(props) { 9 const state = reactive({ 10 indeterminate: true, 11 checkAll: false, 12 checkedData2: [],//已選項(對象數組)頁面展示使用 13 checkedDataId2: [],//已選項(id數組)后續改變值要用,所以不能直接使用props.checkedDataId 14 })
監聽props
15 watch( 16 props, 17 newProps => {
       將已選項id數組轉為字符串,方便后續匹配數據
18 const valStr = newProps.checkedDataId.join()
       初始化數組,避免重復push數據
19 state.checkedData2 = [] 20 state.checkedDataId2 = []
       循環所有備選項。由於已選項數組里只有id,所有此處將id進行匹配,將匹配的值push進checkData2,也就是頁面顯示的已選項的值。
21 newProps.optionAll.forEach((item) => { 22 if (valStr.indexOf(item.id) > -1) { 23 state.checkedData2.push(item) 24 } 25 })
       為checkedDataId2賦值,為后續刪除操作做准備
26 state.checkedDataId2 = newProps.checkedDataId 27 },
      immediate必須加,表示立即執行,否則監聽無效
28 { deep: true, immediate: true }, 29 )

    監聽checkedDataId2,當此字段值改變時,對應的改變checkData2的值,也就是頁面頁面‘已選’的展示數據
30 watch( 31 () => state.checkedDataId2, 32 val => { 33 state.indeterminate = !!val.length && val.length < props.optionAll.length 34 state.checkAll = val.length === props.optionAll.length 35 const valStr = val.join() 36 state.checkedData2 = [] 37 props.optionAll.forEach((item) => { 38 if (valStr.indexOf(item.id) > -1) { 39 state.checkedData2.push(item) 40 } 41 }) 42 }, 43 { deep: true, immediate: true }, 44 ) 45
    用戶點擊全選按鈕 46 const onCheckAllChange = (e) => { 47 /* 實現數組淺拷貝,否則刪除已選項也會刪除備選項optionAll */ 48 const newArr = props.optionAll.concat() 49 Object.assign(state, { 50 checkedData2: e.target.checked ? newArr : [], 51 indeterminate: false, 52 }) 53 54 state.checkedDataId2 = [] 55 if (e.target.checked) {
       全選
56 props.optionAll.forEach(item => { 57 state.checkedDataId2.push(item.id) 58 }) 59 } else { 60 state.checkedDataId2 = [] 61 } 62 } 63
    刪除已選項 64 const removeItem = val => {
     匹配刪除id的位置,將其從checkedDataId2中移除,由於有監聽checkedDataId2,所以后續操作都在監聽中完成
65 const index = state.checkedDataId2.indexOf(val) 66 state.checkedDataId2.splice(index, 1) 67 } 68 69 return { 70 ...toRefs(state), 71 onCheckAllChange, 72 removeItem, 73 } 74 }, 75 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM