完整代码最下面会呈现给大家,这里主要将几个需要注意的点。

第一,结构的最上边是标题栏,但是由于标题栏默认时,当我们添加按钮时会超出界限,所以需要控制一下输入框的长度就没问题了。

.product-name-input {
  width: 200px;
}

第二,树形结构的表格,需要特别注意行数据和列数据都需要唯一的key,如果没有指定唯一的key会出现一些稀奇古怪的错误。一些静态数据,想我的例子,手动赋值key,当我们时请求后台数据时,可以使用rowKey参数,record.id此处的id指你的数据dataSource中的id字段。

<a-table :columns="columns" :data-source="dataSource" bordered :customRow="showModal"
    childrenColumnName="provicechildren" :rowKey="record => record.key" :pagination="dataParams">
</a-table>

第三,树形结构的表格,还需要注意的一个点就是我们后台传过来的数据,子数据可能并不是children,这个时候我们可以使用childrenColumnName参数指定我们的子数据。

const dataSource = ref([
  {
    key: 1,
    name: 'John Brown sr.',
    age: 60,
    address: 'New York No. 1 Lake Park',
    provicechildren: [    //默认时children
      {
        key: 11,
        name: 'John Brown',
        age: 42,
        address: 'New York No. 2 Lake Park',
      },
    ]
  }
]);

第四,在树形表格结构中加上可编辑的单元格,从代码中我们就已经看出,在编辑和保存时,我们都需要key,所以key的存在和唯一性是非常重要的。并且我们可以根据每列的名称选择编辑哪列。

<template #bodyCell="{ column, text, record }">
      <template v-if="column.dataIndex === 'age'">
        <div class="editable-cell">
          <div v-if="editableData[record.key]" class="editable-cell-input-wrapper">
            <a-input v-model:value="editableData[record.key].age" @pressEnter="save(record.key)" />
            <check-outlined class="editable-cell-icon-check" @click="save(record.key)" />
          </div>
          <div v-else class="editable-cell-text-wrapper">
            {{ text || ' ' }}
            <edit-outlined class="editable-cell-icon" @click="edit(record.key)" />
          </div>
        </div>
      </template>
    </template>

完整代码如下:

<template>
  <a-page-header title="XXXXX">
    <template #extra>
      <a-input class="product-name-input" placeholder="请输入省份名称" v-model:value="searchText" />
      <a-button @click="queryProvinceTree()">查询</a-button>
      <a-button @click="reset()">重置</a-button>
    </template>
  </a-page-header>
  <a-table :columns="columns" :data-source="dataSource" bordered :customRow="showModal"
    childrenColumnName="provicechildren" :rowKey="record => record.key" :pagination="dataParams">
    <template #bodyCell="{ column, text, record }">
      <template v-if="column.dataIndex === 'age'">
        <div class="editable-cell">
          <div v-if="editableData[record.key]" class="editable-cell-input-wrapper">
            <a-input v-model:value="editableData[record.key].age" @pressEnter="save(record.key)" />
            <check-outlined class="editable-cell-icon-check" @click="save(record.key)" />
          </div>
          <div v-else class="editable-cell-text-wrapper">
            {{ text || ' ' }}
            <edit-outlined class="editable-cell-icon" @click="edit(record.key)" />
          </div>
        </div>
      </template>
    </template>
  </a-table>
</template>
<script setup>
import { computed, defineComponent, reactive, ref } from 'vue';
import { CheckOutlined, EditOutlined } from '@ant-design/icons-vue';
import { cloneDeep } from 'lodash';
CheckOutlined
EditOutlined
const searchText = ref("");
const columns = [
  {
    title: 'Name',
    dataIndex: 'name',
    key: 'name',
  },
  {
    title: 'Age',
    dataIndex: 'age',
    key: 'age',
    width: '12%',
  },
  {
    title: 'Address',
    dataIndex: 'address',
    width: '30%',
    key: 'address',
  },
];
const dataSource = ref([
  {
    key: 1,
    name: 'John Brown sr.',
    age: 60,
    address: 'New York No. 1 Lake Park',
    provicechildren: [
      {
        key: 11,
        name: 'John Brown',
        age: 42,
        address: 'New York No. 2 Lake Park',
      },
      {
        key: 12,
        name: 'John Brown jr.',
        age: 30,
        address: 'New York No. 3 Lake Park',
        provicechildren: [
          {
            key: 121,
            name: 'Jimmy Brown',
            age: 16,
            address: 'New York No. 3 Lake Park',
          },
        ],
      },
      {
        key: 13,
        name: 'Jim Green sr.',
        age: 72,
        address: 'London No. 1 Lake Park',
        chilprovicechildrendren: [
          {
            key: 131,
            name: 'Jim Green',
            age: 42,
            address: 'London No. 2 Lake Park',
            provicechildren: [
              {
                key: 1311,
                name: 'Jim Green jr.',
                age: 25,
                address: 'London No. 3 Lake Park',
              },
              {
                key: 1312,
                name: 'Jimmy Green sr.',
                age: 18,
                address: 'London No. 4 Lake Park',
              },
            ],
          },
        ],
      },
    ],
  },
  {
    key: 2,
    name: 'Joe Black',
    age: 32,
    address: 'Sidney No. 1 Lake Park',
  },
  {
    key: 3,
    name: 'Joe Black',
    age: 32,
    address: 'Sidney No. 1 Lake Park',
  },
  {
    key: 4,
    name: 'Joe Black',
    age: 32,
    address: 'Sidney No. 1 Lake Park',
  },
  {
    key: 5,
    name: 'Joe Black',
    age: 32,
    address: 'Sidney No. 1 Lake Park',
  },
  {
    key: 6,
    name: 'Joe Black',
    age: 32,
    address: 'Sidney No. 1 Lake Park',
  },
]);
const dataParams = reactive({
  current: 1,
  pageSize: 5,
})
//查询省份树--请求后台接口
const queryProvinceTree = () => {
  console.log("查询省份树!");
}
//清空查询条件
const reset = () => {
  searchText.value = "";
};
// 翻页事件--并且同时需要刷新列表
const tableChange = (option) => {
  dataParams.current = option.current
}
const editableData = reactive({});

const edit = key => {
  debugger
  editableData[key] = cloneDeep(dataSource.value.filter(item => key === item.key)[0]);
  console.log(key)
};

const save = key => {
  Object.assign(dataSource.value.filter(item => key === item.key)[0], editableData[key]);
  delete editableData[key];
};
</script>
<style scoped>
.product-name-input {
  width: 200px;
}

.editable-cell-input-wrapper,
.editable-cell-text-wrapper {
  padding-right: 24px;

}

.editable-cell-text-wrapper {
  padding: 5px 24px 5px 5px;
}

.editable-cell-icon,
.editable-cell-icon-check {
  position: absolute;
  right: 0;
  width: 20px;
  cursor: pointer;
}

.editable-cell-icon {
  margin-top: 4px;
  margin-right: 10px;
}

.editable-cell-icon-check {
  margin-top: 8px;
  margin-right: 10px;
}
</style>
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐