vxe-table 实现复杂的表格功能。

一、界面展示

在这里插入图片描述

二、功能描述

  • 添加:实现在表格头部添加一行记录,工号会自动生成,其他数据为空。
  • 修改:点击表格单元格,可以实现修改指定字段内容,失焦自动保存修改后的数据。
  • 删除:弹出确认对话框,点击 yes 后,删除当前行。
    在这里插入图片描述
  • 排序:年龄
  • 筛选:性别、年龄、省份 >> 实现都不一样
  • 操作列右固定:由于表格宽度是指定的,所以表格列信息显示不全。这里采用了操作列右固定的形式,左右拖拽滚动条即可显示隐藏列数据。
  • 省份对话框:点击省份单元格,会弹出对话框,在对话框内显示省份树信息,选择某个节点,点击确定,省份自动填写到点击的单元格内。
    在这里插入图片描述
  • 城市对话框:点击城市单元格,会先进行此行省份数据是否为空。当省份为空时,弹出提示信息。省份不为空时,显示城市对话框,选择某行,点击确定,城市自动填写到点击的单元格内。
    在这里插入图片描述

三、代码实现

1. 代码

<template>
  <div>
    <div class="box">
      <!-- 添加行数据按钮 -->
      <div @click="add" class="addBtn">
        <a-icon type="plus" />添加
      </div>
      <!-- 表格 -->
      <vxe-table
        ref="xTable"
        auto-resize
        show-overflow
        header-align="center"
        row-id="id"
        :data="tableData"
        :row-config="{isHover:true}"
        :edit-config="{ trigger: 'click', mode: 'cell', showIcon: false }"
        @cell-click="cellClick"
      >
        <vxe-column field="id" title="工号" width="100" align="center"></vxe-column>
        <vxe-column
          field="name"
          title="姓名"
          width="100"
          align="center"
          :edit-render="{ name: 'input' }"
          :filters="[]"
          :filter-method="filterName"
        ></vxe-column>
        <vxe-column
          field="age"
          title="年龄"
          width="100"
          align="center"
          sortable
          :edit-render="{ name: 'input' }"
        ></vxe-column>
        <vxe-column
          field="sex"
          title="性别"
          width="100"
          align="center"
          :edit-render="{}"
          :filters="[{label: '男', value: 1}, {label: '女', value: 0}]"
          :filter-multiple="false"
        >
          <template #default="{ row }">
            <span>{{ formatSex(row.sex) }}</span>
          </template>
          <template #edit="{ row }">
            <vxe-select v-model="row.sex" transfer>
              <vxe-option
                v-for="item in sexList"
                :key="item.key"
                :value="item.key"
                :label="item.value"
              ></vxe-option>
            </vxe-select>
          </template>
        </vxe-column>
        <vxe-column
          field="province"
          title="省份"
          width="100"
          :edit-render="{ name: 'input' }"
          :filters="[{ data: '' }]"
          :filter-method="filterProvince"
        >
          <template #filter="{ $panel, column }">
            <input
              type="type"
              v-for="(option, index) in column.filters"
              :key="index"
              v-model="option.data"
              @input="$panel.changeOption($event, !!option.data, option)"
            />
          </template>
        </vxe-column>
        <vxe-column field="city" title="城市" width="100" :edit-render="{ name: 'input' }"></vxe-column>
        <vxe-column field="quit" title="离职" width="100">
          <template #default="{ row }">
            <a-checkbox :checked="row.quit" @change="quitChange(row)"></a-checkbox>
          </template>
        </vxe-column>
        <vxe-column title="操作" fixed="right" width="100">
          <template #default="{ row }">
            <a-popconfirm
              title="你确定要删除此条数据吗?"
              ok-text="Yes"
              cancel-text="No"
              @confirm="confirmDelete(row)"
            >
              <vxe-button type="text" status="primary" content="删除"></vxe-button>
            </a-popconfirm>
          </template>
        </vxe-column>
      </vxe-table>
      <!-- 省份对话框 -->
      <a-modal
        v-model="provinceModal"
        title="省份"
        @ok="provinceModalClose"
        ok-text="确定"
        cancel-text="取消"
        destroy-on-close
      >
        <a-tree :treeData="provinceTree" @select="provinceTreeSelect" defaultExpandAll></a-tree>
      </a-modal>
      <!-- 城市对话框 -->
      <a-modal
        v-model="cityModal"
        title="省份"
        @ok="cityModalClose"
        ok-text="确定"
        cancel-text="取消"
        destroy-on-close
      >
        <vxe-table
          border
          ref="xTable1"
          :data="cityTable"
          :radio-config="{highlight: true}"
          @radio-change="radioChange"
        >
          <vxe-column type="radio" width="60"></vxe-column>
          <vxe-column field="city" title="城市"></vxe-column>
        </vxe-table>
      </a-modal>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        {
          id: 1001,
          name: '小红',
          age: 23,
          sex: 0,
          province: '广东省',
          city: '广州',
          quit: false
        },
        {
          id: 1002,
          name: '小白',
          age: 26,
          sex: 1,
          province: '山东省',
          city: '青岛',
          quit: true
        }
      ],
      sexList: [{ key: 0, value: '女' }, { key: 1, value: '男' }],
      selectRow: {}, // 选中某行
      provinceModal: false, // 省份对话框
      provinceTree: [], // 省份树数据
      cityModal: false, // 城市对话框
      treeSelect: '', // 省份树节点选择
      cityTable: [], // 城市表格数据
      cityData: [
        {
          province: '广东省',
          city: ['广州', '珠海'],
        }, {
          province: '山东省',
          city: ['青岛', '济南'],
        }, {
          province: '北京',
          city: ['海淀区', '朝阳区', '昌平区'],
        }, {
          province: '黑龙江',
          city: ['哈尔滨', '七台河', '佳木斯'],
        },
      ],
      citySelect: '' // 城市表格选择
    }
  },
  mounted() {
    // 异步加载筛选数据
    setTimeout(() => {
      const $table = this.$refs.xTable
      if ($table) {
        const nameColumn = $table.getColumnByField('name')
        if (nameColumn) {
          $table.setFilter(nameColumn, [
            { label: 'id大于1000', value: 1000 },
            { label: 'id大于1004', value: 1004 }
          ])
        }
      }
    }, 500)
  },
  methods: {
    /* 功能:格式化性别 */
    formatSex(value) {
      let result = this.sexList.filter(item => item.key === value)
      return result[0].value
    },
    /* 功能:离职多选框变化 */
    quitChange(row) {
      row.quit = !row.quit
    },
    /* 功能:姓名列筛选 */
    filterName({ value, row }) {
      return row.id >= value
    },
    /* 功能:省份列筛选 */
    filterProvince({ option, row }) {
      return row.province.includes(option.data)
    },
    /* 功能:点击表格的单元格 */
    cellClick({ row, column }) {
      this.selectRow = row
      if (column.property === 'province') {
        this.getprovinceTree()
        this.provinceModal = true
      } else if (column.property === 'city') {
        if (this.selectRow.province === '') {
          this.$message.warning('请先选择省份!');
        } else {
          this.getCityTable()
          this.cityModal = true
        }
      }
    },
    /* 功能:省份对话框确认 */
    provinceModalClose() {
      this.selectRow.province = this.treeSelect
      this.treeSelect = ''
      this.provinceModal = false
    },
    /* 功能:城市对话框确认 */
    cityModalClose() {
      this.selectRow.city = this.citySelect
      this.citySelect = ''
      this.cityModal = false
    },
    /* 功能:获取省份树数据 - 为了模拟调接口 */
    getprovinceTree() {
      this.provinceTree = []
      let data = {
        title: '中国',
        key: 'china',
        children: [
          {
            title: '广东省',
            key: 'gd',
          }, {
            title: '山东省',
            key: 'sd',
          }, {
            title: '北京',
            key: 'bj',
          }, {
            title: '黑龙江省',
            key: 'hlj',
          },
        ]
      }
      this.provinceTree.push(data)
    },
    /* 功能:省份树节点选择 */
    provinceTreeSelect(selectedKeys, info) {
      // 将选中的省份赋值给表格
      this.treeSelect = info.node.dataRef.title
      // 此处不做城市清空操作(自行优化)
    },
    /* 功能:获取城市表格数据 */
    getCityTable() {
      // 获取对应城市的数据
      let data = this.cityData.filter(item => item.province === this.selectRow.province)
      // 修改数据格式
      this.cityTable = data[0].city.map(item => {
        let obj = {}
        obj['city'] = item
        return obj
      })
    },
    /* 功能:城市表格单选变化 */
    radioChange({ row }) {
      this.citySelect = row.city
    },
    /* 功能:添加行记录 */
    add() {
      let newId = 1001 + this.tableData.length
      let newData = {
        id: newId,
        name: '',
        age: '',
        sex: 0,
        province: '',
        city: '',
        quit: false
      }
      this.tableData.unshift(newData)
      this.$message.success('新增成功!');
    },
    /* 功能:删除一行记录 */
    confirmDelete(row) {
      let newData = this.tableData.filter(item => item.id !== row.id)
      this.tableData = newData
      this.$message.success('删除成功!');
    },
  }


}
</script>

<style>
.box {
  margin: 50px;
  width: 700px;
}

.addBtn {
  margin: 5px;
  cursor: pointer;
}
</style>

2.参数解释

1)vxe-table

属性名说明默认值 / 类型
height表格的高度;支持铺满父容器或者固定高度,如果设置 auto 为铺满父容器(如果设置为 auto,则必须确保存在父节点且不允许存在相邻元素)number
max-height表格的最大高度number
auto-resize自动监听父元素的变化去重新计算表格(对于父元素可能存在动态变化、显示隐藏的容器中、列宽异常等场景中的可能会用到)false
header-align所有的表头列的对齐方式left, center, right
radio-change只对 type=radio 有效,当手动勾选并且值发生改变时触发的事件{ newValue, oldValue, row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, $event }
cell-click单元格被点击时会触发该事件{ row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, triggerRadio, triggerCheckbox, triggerTreeNode, triggerExpandNode, $event }
sortable是否允许列排序false

2)column-config:列的默认参数

属性名说明默认值 / 类型
isHover当鼠标移到列头时,是否要高亮当前列头false
resizable每一列是否启用列宽调整false
isCurrent当鼠标点击列头时,是否要高亮当前列false
useKey是否需要为每一列的 VNode 设置 key 属性(非特殊情况下不需要使用)false
width每一列的宽度number, string
minWidth每一列的最小宽度number, string

3)edit-config:可编辑配置项

属性名说明默认值 / 类型
trigger触发方式manual(手动触发方式,只能用于 mode=row),click(默认,点击触发编辑),dblclick(双击触发编辑)
mode编辑模式cell(默认,单元格编辑模式),row(行编辑模式)

4)row-config:行配置信息

属性名说明默认值 / 类型
isHover当鼠标移到行时,是否要高亮当前行false
isCurrent当鼠标点击行时,是否要高亮当前行false

四、库安装使用

1. 安装教程

ant Design 、vxe-table 安装教程

2. 官方文档

vxe-table文档
ant design 文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值