1. 程式人生 > >Vue:Elementui中的Tag與頁面其它元素相互互動的兩三事

Vue:Elementui中的Tag與頁面其它元素相互互動的兩三事

前言

公司系統在用elementui做後臺開發,不免遇到一些需要自己去根據原有的功能上,加一些互動的功能。
今天來介紹下我在用elementUi裡的Tag標籤與多選框互動的過程,東西聽上去很簡單,但就是越簡單的東西越容易出一些問題。官方tag文件: elementUi-tag標籤

效果圖:

思路

一、多選框勾選,出現對應的tag:
1.利用watch監聽多選框繫結的值 A(陣列)的變化;
2.根據 A的變化,迴圈拿到勾選多選框的id對應的name,將id以及對應的name組成新的物件陣列;
3.將上一步得到的物件陣列,去重(產品要求,出現的tag裡不能有重複的)得到結果 B

4.將 B賦值給tags,迴圈展示出來;

二、點選tag上的刪除按鈕,刪除當前的tag,並將對應勾選的多選框取消勾選:
1.點選tag刪除的按鈕的時候,拿到當前tag的id C
2.執行方法,去除掉A裡的C
3.watch事件重新進入到第一步的方法;

總結:監聽多選框對應的model A,根據A的變化,取到對應的id與name,賦值給tag作展示,tag的刪除事件反過來在去控制A的變化,重新進入watch事件裡的方法

聽起來挺簡單,思路大概也明確,先講上述思路對應的程式碼,後邊再講遇到的問題、坑

程式碼

複製整一塊程式碼到你的elementUi專案裡就能看到效果

<template>
  <div>
    <el-row type="flex" justify="bettwen">
      <el-col :span="15">
        <!-- 表單 -->
        <el-form :model="tempForm" ref="tempForms">
          <el-form-item label="請選擇人員">
            <!-- 多選人員 -->
            <el-checkbox-group v-model="tempForm.checkboxGroup5" size="small">
              <el-checkbox border v-for="(item,index) in checkBox" @change="perChange(item)" :label="item.id" :key="index">{{item.name}}</el-checkbox>
            </el-checkbox-group>
            <!-- 多選人員 end-->
          </el-form-item>
        </el-form>
        <!-- 表單 end-->
        <!-- tag展示區 -->
        <el-row>
          <el-tag class="tagClass" v-for="(tag,index) in tags" :key="index" closable @close="handleClose(tag)" :type="tag.id">
            {{tag.name}}
          </el-tag>
          <el-button v-if="tags.length>0" @click="clearAll" plain>全部刪除</el-button>
        </el-row>
        <!-- tag展示區 end-->
      </el-col>
     
    </el-row>
  </div>
</template>
<script>
export default {
  name: 'kk',
  mounted() {},
  data() {
    return {
      msg: 'Welcome to Your Vue.js App',
      tags: [],
      tempForm: {
        checkboxGroup5: [], //選擇的人員
      },
      detailData: [],
      checkBox: [{
          name: '小紅',
          id: '101'
        },
        {
          name: '小黃',
          id: '100'

        }, {
          name: '小明',
          id: '102'

        }, {
          name: '小明',
          id: '102'

        }
      ],
     
    }
  },
  methods: {
    clearAll() { //全部清空資料
      this.tags = []
      this.tempForm.checkboxGroup5 = []
    },
    perChange(item) {
      this.detailData.push(item)
    },
    handleClose(tag) { //標籤的刪除事件
      // 去掉當前刪除的tag
      let yourChoseTags = this.tempForm.checkboxGroup5

      this.tempForm.checkboxGroup5 = yourChoseTags.filter(item => {
        if (tag.id !== item) {
          return true
        }
      })

     
    },
    delRepeat(arr) { //陣列物件去重
      return Object.values(
        arr.reduce((obj, next) => {
          var key = JSON.stringify(next);
          return (obj[key] = next), obj;
        }, {}),
      );
    },
    moreArr() {
      let yourChose = this.tempForm.checkboxGroup5
      let tempTags = []

      tempTags = this.baseDataDetail(yourChose, this.checkBox, tempTags)
      this.detailData = tempTags
    },
    baseDataDetail(yourChose, baseData, callBack) { //封裝的陣列方法
      let temp = callBack
      // 迴圈兩個資料拿到選擇的checkbox的id對應的初始資料
      yourChose.forEach(item => {
        baseData.forEach(itemSecond => {
          if (item === itemSecond.id) {
            temp.push(itemSecond)
          }
        })
      })
      return temp
    },

  },
  watch: {
    detailData() {
      let tempArr = Object.assign([], this.detailData)
      tempArr = this.delRepeat(tempArr)
      // console.log(tempArr)
      this.tags = tempArr
    },
    "tempForm.checkboxGroup5" () {
      this.moreArr()
    },
  }
}

</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.tempArea {
  /*width: 100%;*/
}
.tagClass{
  margin-right: 10px;
}

</style>

值得注意的點:

1.我在多選框繫結值 tempForm.checkboxGroup5的監聽事件裡的方法的最後,得到了一個可能會有重複資料(重複id跟name),再將這個含有重複資料陣列物件賦值給另一個數組 detailData,在watch監聽這個陣列,去完重後,賦值給tags做展示。
為什麼這樣做,是因為,我們的需求裡,除了在當前頁面多選框選擇人員,還有一個選擇全公司員工的元件,這樣不管從哪個渠道選擇的人員都能最後將結果指向 detailData,保證渲染正確

2.陣列物件去重,初始資料裡可能會有重id、重名的物件(小明),即便繫結多選框的model值裡不會有重複的id,但在 利用id取對應name的時候,還是會檢測出多條,這樣tag就可能會顯示重複的
所以利用這個方法,就能保證最後處理好的資料沒有重複的,tag不會顯示多個一樣的,
但這個方法有點不靈活的地方就是,你要處理的資料({id:1,name:'小明',type:now})必須id、name,type都重複的時候,才會被去重,
拓展:可根據你設定的陣列物件裡的某個屬性動態去重


//陣列物件去重:id、name,type都重複的時候,才會被去重
delRepeat(arr) { 
      return Object.values(
        arr.reduce((obj, next) => {
          var key = JSON.stringify(next);
          return (obj[key] = next), obj;
        }, {}),
      );
    }
//拓展:根據你設定的陣列物件裡的name屬性動態去重
 baseDel(arr) {
      const res = new Map();
      return arr.filter((item) => !res.has(item.name) && res.set(item.name, 1))
    },
3.我一開始是在多選框的change事件上來做tag的展示邏輯,因為change事件裡可以同時拿到當前選擇的name和id,但是,change的時候,你不知道這是在勾選還是在取消勾選,這樣tags的展示就會出問題;

這個邏輯可能不太完美,因為有可能你的人員是從其他元件裡選來的,所以當你刪除tag的時候,會可能出問題(暫時先不討論這種情況)

歡迎大家來指正和補充,或者你的業務需求以及解決方式,撒花

來源:https://segmentfault.com/a/1190000016500866