基于Vue2.0 二次封装el-table组件 实现表格搜索,隐藏、显示列等功能

2,022 阅读2分钟

封装背景

管理后台需要大量的表格数据以及操作,可是用现有的element-ui,就显得代码有些冗余,维护起来乱糟糟的,所以就想到要将element-ui的table组件,分页组件进行二次的封装.以下内容是我参照juejin.cn/post/702214… 这篇文章进行修改得来的,仅供参考哦~

封装表格

子组件

<div>
    <!--操作按钮-->
    <el-row :gutter="20" class="btn-operation">
      <el-col :span="5">
        <el-switch v-model="switchValue" active-text="远程搜索" inactive-text="本地搜索" :active-value="1" :inactive-value="0" />
      </el-col>
      <el-col :span="6">
        <el-input v-model="tableContent" placeholder="请输入内容" @keyup.native.enter="searchContent">
          <el-button slot="append" icon="el-icon-search" @click="searchContent" />
        </el-input>
      </el-col>
      <el-col :span="6">
        <el-dropdown trigger="click">
          <el-button icon="el-icon-s-operation" size="mini">列设置</el-button>
          <el-dropdown-menu slot="dropdown">
            <span class="title">列设置</span>
            <el-tree draggable :data="columns" :props="defaultProps" :allow-drop="allowDrop" @node-drop="handleDrop">
              <span slot-scope="{ node, data }" class="tree-table-setting">
                <el-switch v-model="data.show" @change="saveTableColumns" />
                <span>{{ node.label }}</span>
              </span>
            </el-tree>
          </el-dropdown-menu>
        </el-dropdown>
      </el-col>
    </el-row>

    <!--表格-->
    <div>
      <el-table
        ref="table"
        :key="tableKey"
        :data="tableData"
        :height="tableHeight"
        :row-style="{ height: '40px' }"
        :cell-style="{ borderRight: 'none' }"
        :header-cell-style="{ height: '40px', padding: 0, background: '#f6f8fa', color: '#333' }"
        border
        size="mini"
        tooltip-effect="dark"
        highlight-current-row
        @row-click="handelTableClick"
        @selection-change="handleSelectionChange"
      >
        <el-table-column align="center" type="selection" />
        <template v-for="item in columns">
          <el-table-column
            v-if="item.show"
            :key="item.prop"
            show-overflow-tooltip
            :prop="item.prop"
            :sortable="item.sortable"
            :label="item.label"
            :width="item.width"
            :resizable="item.resizable"
          >
            <template slot-scope="scope">
              <span>{{ scope.row[item.prop] }}</span>
            </template>
          </el-table-column>
        </template>
        <el-table-column />
      </el-table>
      <el-pagination
        class="pagination-container"
        :background="background"
        :current-page.sync="currentPage"
        :page-size.sync="pageSize"
        :layout="layout"
        :page-sizes="pageSizes"
        :total="total"
        v-bind="$attrs"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>

  </div>
export default {
  props: {
    // 控制列
    columns: {
      type: Array,
      default: () => []
    },
    // 表格数据
    tableData: {
      type: Array,
      default: () => []
    },
    // 列表总数
    total: {
      required: true,
      type: Number
    },
    // 当前页
    page: {
      type: Number,
      default: 1
    },
    // 每页展示数量
    limit: {
      type: Number,
      default: 20
    },
    // 每页展示数量
    pageSizes: {
      type: Array,
      default() {
        return [10, 20, 30, 50]
      }
    },
    // 操作项
    layout: {
      type: String,
      default: 'total, sizes, prev, pager, next, jumper'
    },
    // 分页背景
    background: {
      type: Boolean,
      default: false
    },
    autoScroll: {
      type: Boolean,
      default: true
    },
    hidden: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      // 表格key
      tableKey: 1,
      // 默认表格高度
      tableHeight: 300,
      // 列设置中 tree配置
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      tableContent: '', // 搜索的表格内容

      switchValue: 0 // 远程/本地搜索按钮控制 0本地 1远程

    }
  },
  computed: {
    currentPage: {
      get() {
        return this.page
      },
      set(val) {
        this.$emit('update:page', val)
      }
    },
    pageSize: {
      get() {
        return this.limit
      },
      set(val) {
        this.$emit('update:limit', val)
      }
    }
  },
  watch: {
    'tableContent'(val) {
      if (!val) { // 清空搜索项
        this.$emit('clear-content')
      }
    }
  },
  mounted() {
    this.init()
  },
  updated() {
    // 解决操作之后表格抖动的问题
    this.$refs.table.doLayout()
  },
  methods: {
    /**
      * @author: xxx
      * @description: 搜索表格内容
      * 1为远程(后台搜索) 0为本地搜索
      */
    searchContent() {
      if (this.switchValue === 0) { // 本地搜索
        const search = this.tableContent
        const arr = this.tableData.filter(item => {
          return Object.keys(item).some(key => {
            if (String(item[key]).toLowerCase().indexOf(search) > -1) { // 搜索到相关信息
              return item
            }
          })
        })
        this.$emit('search-content', arr)
      } else { // 远程搜索
        console.log('------远程搜索---------')
      }
    },
    init() {
      // 判断本地是否有表格配置数据 ? 加载 : 忽略
      // 获取表格数据
      // 重设表格高度
    },
    allowDrop(draggingNode, dropNode, type) {
      // 仅允许Tree节点上下拖动
      return type !== 'inner'
    },
    // Tree 拖动时更新表格
    handleDrop() {
      this.tableKey++
      // 保存表格配置
      this.saveTableColumns()
    },
    // 重置表格列设置
    resetTable() {
      // ... 忽略
    },
    // 显示隐藏切换 && 保存表格配置
    saveTableColumns() {
      window.sessionStorage.setItem('clueTable', this.columns)
    },
    // 选中表格行
    handelTableClick(row) {
      // ... 省略业务逻辑
    },
    // table多选操作
    handleSelectionChange(val) {
      // ... 省略业务逻辑
    },
    // 页码切换
    handleSizeChange(val) {
      this.$emit('pagination', { page: this.currentPage, limit: val })
    },
    // 每页展示数量切换
    handleCurrentChange(val) {
      this.$emit('pagination', { page: val, limit: this.pageSize })
    }
  }
}

以上js中的代码,像tableHeight这类参数也可以单独从父组件中传进来使用,毕竟每个页面的表格高度都多少有所不同嘛

父组件 在父组件中,直接引入刚才所写好的组件,进行使用即可

 <TableTest
      :table-data="tableData"
      :columns="tableColumns"
      :total="pageTotal"
      :page.sync="actQueryForm.current"
      :limit.sync="actQueryForm.size"
      @columns-change="onColumnsChange"
      @selection-change="onTableSelectionChange"
      @sort-change="onTableSortChange"
      @search-content="searchContent"
      @clear-content="clearContent"
      @pagination="getActList"
      />
import TableTest from '../TableTest'
export default {
    data(){
        return {
            tableData: [
        { desc: '123as', name: '张三', age: 18, sex: '男' },
        { desc: '123as', name: '李四', age: 22, sex: '女' },
        { desc: '123as', name: '王五', age: 10, sex: '男' },
        { desc: '123as', name: '张三', age: 13, sex: '男' },
        { desc: '123as', name: '李四', age: 23, sex: '女' },
        { desc: '123as', name: '王五', age: 14, sex: '男' }
      ],
      tableColumns: [
        {
          prop: 'name', // 对应列内容的字段名
          label: '姓名', // 显示的标题
          width: '', // 对应列的宽度
          resizable: true, // 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真)
          show: true, // 展示与隐藏
          sortable: false // 对应列是否可以排序
        },
        {
          prop: 'sex', // 对应列内容的字段名
          label: '性别', // 显示的标题
          width: '', // 对应列的宽度
          resizable: true, // 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真)
          show: true, // 展示与隐藏
          sortable: false // 对应列是否可以排序
        },
        {
          prop: 'age', // 对应列内容的字段名
          label: '年龄', // 显示的标题
          width: '', // 对应列的宽度
          resizable: true, // 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真)
          show: true, // 展示与隐藏
          sortable: false // 对应列是否可以排序
        },
        {
          prop: 'desc', // 对应列内容的字段名
          label: '描述', // 显示的标题
          width: '', // 对应列的宽度
          resizable: true, // 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真)
          show: true, // 展示与隐藏
          sortable: false // 对应列是否可以排序
        }
      ],
       }
    },
    created() {
        // 在初始化阶段保存tableData的原始数据目的是为了在搜索时,清空数据导致数据的丢失(项目中可以在请求完tableData的数据,存到本地即可)
        sessionStorage.setItem('table_data', JSON.stringify(this.tableData)) // 保存原始数据
  },
  methods:{
     // 查询表格数据
    searchContent(arr) {
      this.tableData = arr
    },
    // 查询后清空输入框信息
    clearContent() {
      this.tableData = JSON.parse(window.sessionStorage.getItem('table_data'))
    },
  }
}