ElementUI实现自由设置table列属性,并且修改列的显示顺序

241 阅读2分钟

需求:用户想自由选取某几列进行显示,并且可以修改列的顺序

image.png

先看实现的页面,字段的顺序是直接手动拖动的

image.png image.png

代码

组件tableui

用到了vuedraggable插件 npm i -S vuedraggable

<template>
  <div>
    <el-dialog :visible.sync="dialogVisible" width="30%" title="字段配置">
      <el-tabs v-model="activeName">
        <el-tab-pane label="字段选择" name="fieldsChosen">
          <el-checkbox
            v-model="checkAll"
            @change="handleCheckAllChange"
            :indeterminate="isIndeterminate"
            >全部</el-checkbox
          >
          <el-checkbox-group
            v-model="checkedColumn"
            @change="handleCheckedList"
          >
            <el-checkbox
              style="width: 40%"
              v-for="item in columns"
              :label="item.name"
              :key="item.name"
              >{{ item.name }}</el-checkbox
            >
          </el-checkbox-group>
        </el-tab-pane>

        <el-tab-pane label="字段顺序" name="fieldSorted">
          <vuedraggable
            :list="checkedColumn"
            @start="dragging = true"
            @end="dragging = false"
            animation="300"
          >
            <div
              v-for="item in checkedColumn"
              style="
                background-color: gainsboro;
                margin: 10px;
                padding: 5px;
                text-align: center;
                cursor: pointer;
              "
              :key="item"
            >
              {{ item }}
            </div>
          </vuedraggable>
        </el-tab-pane>
      </el-tabs>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisiblefalse" class="buttonRight"
          >取 消</el-button
        >
        <el-button type="primary" @click="submit" class="buttonRight"
          >确 定</el-button
        >
      </span>
    </el-dialog>
  </div>
</template>
<script>
import vuedraggable from "vuedraggable";
export default {
  name: "Test",
  components: {
    vuedraggable,
  },
  props: {
    dialogVisible: {
      type: Boolean,
    },
    // 列信息
    checkedColumns: {
      type: Array,
    },
  },
  data() {
    return {
      dragging: false,
      expandRowKeys: [],
      activeName: "fieldsChosen",
      checkAll: false,
      isIndeterminate: true,
      fieldsTemp: [], //存放按指定顺序排列的fields数组
      fields: [],
      deepCloneArray: [],
      checkedColumnsSelect: [],
      checkedColumn: [],
    };
  },
  computed: {
    fieldList() {
      return this.checkedColumns;
    },
    columns() {
      return this.checkedColumns;
    },
  },
  watch: {
    checkedColumns(val) {
      this.checkedColumn = JSON.parse(JSON.stringify(val));
      //这里我只拿了名字
      this.checkedColumn = this.checkedColumn.map((o) => o.name);
    },
  },
  mounted() {
    this.deepCloneArray = JSON.parse(JSON.stringify(this.fields));
  },
  methods: {
    //关弹框
    dialogVisiblefalse() {
      this.$emit("dialogVisiblefalse", false);
    },
    //全选
    handleCheckAllChange(val) {
      this.checkedColumn = val ? this.checkedColumns.map((o) => o.name) : [];
      this.isIndeterminate = false;
    },
    handleCheckedList(val) {
      this.checkedColumnsSelect = val;
      let checkedCount = val.length;
      this.checkAll = checkedCount === this.columns.length;
      this.isIndeterminate =
        checkedCount > 0 && checkedCount < this.columns.length;
    },
     //保存
    submit() {
      //按拖动后的顺序给列表排队,没选择的就不显示
      let index = 0;
      let sortArray = []
      // 这里this.checkedColumn是拖动后的顺序名称列表,将属性的列表按照排序的列表排序
      for (const name of this.checkedColumn) {
        const item = this.fieldList.find((o) => o.name == name);
        if (item) {
          item.index = index;        //index好像没用到
          sortArray.push(item);
          index++;
        }
      }
      //更新表格展示列,把数据传回父组件
      this.$emit("getlabList",sortArray)
      //关弹框
      this.dialogVisiblefalse();      
    }, 
  },
};
</script>
<style lang="scss" scoped>
:deep(.el-dialog__body) {
  padding-top: 0;
}
</style>

原页面 传给组件完整的属性,组件处理好再传回来保存并且渲染

<template>
 <el-button type="primary" @click="handleConfig" size="mini">字段配置</el-button>
 <el-table .....> //原来的写法就行
 //不需要动态的列就原来的写法
 //下边演示的是需要自由设置的列
 <el-table-column
    v-for="item in filterLabList"  
    :key="item.index"
    :label="item.name"
    show-overflow-tooltip
    align="center"
    :prop="item.prop"
  >
  //下边演示不能直接prop渲染,需要处理的列写法,就是一个iF判断
    <template slot-scope="scope">
      <div v-if="item.name == '测试时间'">
        <span>{{ getformatDate(scope.row.gmtCreate) }}</span>
      </div>
    </template>
  </el-table-column>
 </el-table>
 <-- 弹框组件 -->
  <tableui
      :dialogVisible="dialogVisible"
      :checkedColumns="checkedColumns"   //把所有列传给组件
      @getlabList="getlabList"           //这是保存后列按照配置的刷新
      @dialogVisiblefalse="dialogVisiblefalse"  //关弹框
 </tableui>
</template> 
<script>
import tableui from "@/views/components/tableui";
 export default {
 components: {tableui },
  data() {
    return {
    dialogVisible: false,
       checkedColumns: [    //自己列的全部属性
        { name: "日期", prop: "testDate" },
        { name: "项目名称", prop: "testName" },
           ..................
        { name: "测试时间", prop: "gmtCreate" },
      ],
      filterLabList:[]
    }
  },
   mounted() {
      this.getStorageList()   //先去取本地存的顺序列表
   },  
   methods:{
   //取本地
     getStorageList() {
      var storedList = JSON.parse(localStorage.getItem("filterLabList"));
      if (storedList) {
        this.filterLabList = storedList;
      } else {
        this.filterLabList = this.checkedColumns
      }
    },
    //开关弹框
    handleConfig() {
      this.dialogVisible = true;
    },
    dialogVisiblefalse() {
      this.dialogVisible = false;
    },
    //存本地
    getlabList(list) {
      this.filterLabList = list;
      //存一份到本地
      var listString = JSON.stringify(list);
      localStorage.setItem("filterLabList", listString);
    }
   }
  }
  </script>

意思就这么个意思,仅做个参考