在 Vue3 + Element Plus 中生成动态表格,动态修改表格,多级表头,合并单元格

简介: 在 Vue 中,表格组件是使用频率及复杂度排名第一的组件,前端经常需要根据后台返回的数据动态渲染表格,比如动态表格如何生成,因为表格的列并不是固定的,在未知表格具体有哪些列的场景下,前端如何动态渲染表格数据。又或者需要把表格单元格进行合并处理,比如第一列是日期,需要把相同的日期进行合并,这样表格看起来会更加清晰。 本文手把手教你如何在 Vue3 + Element Plus 中创建表格、生成动态表格、创建动态多级表头、表格行合并、列合并等问题。如果你正在搭建后台管理工具,又不想处理前端问题,推荐使用卡拉云 ,卡拉云是新一代低代码开发工具,可一键接入常见数据库及 API ,无需懂前端,仅需拖拽即

在 Vue3 + Element Plus 中生成动态表格,动态修改表格,多级表头,合并单元格

本文完整版:《在 Vue3 + Element Plus 中生成动态表格,动态修改表格,多级表头,合并单元格

在 Vue 中,表格组件是使用频率及复杂度排名第一的组件,前端经常需要根据后台返回的数据动态渲染表格,比如动态表格如何生成,因为表格的列并不是固定的,在未知表格具体有哪些列的场景下,前端如何动态渲染表格数据。又或者需要把表格单元格进行合并处理,比如第一列是日期,需要把相同的日期进行合并,这样表格看起来会更加清晰。 本文手把手教你如何在 Vue3 + Element Plus 中创建表格、生成动态表格、创建动态多级表头、表格行合并、列合并等问题。

如果你正在搭建后台管理工具,又不想处理前端问题,推荐使用卡拉云 ,卡拉云是新一代低代码开发工具,可一键接入常见数据库及 API ,无需懂前端,仅需拖拽即可快速搭建属于你自己的后台管理工具,一周工作量缩减至一天,详见本文文末。

通过本文你可以学到

  • 如何在 Element Plus 中生成动态表格
  • 如何在 Element Plus 中动态修改表格
  • 如何在 Element Plus 中创建动态多级表头

先来展示个「动态修改表格」的最终效果图吧 Vue3 + Element Plus动态修改表格

Vue3 + Element Plus 配置环境

先使用 vue-cli 初始化应用,这里我们选择 vue3 的版本:

vue create kalacloud-vue3-element-plus-table
// OR
npx vue create kalacloud-vue3-element-plus-table

然后安装 UI 框架 Element Plus:

npm install element-plus --save
// OR
yarn add element-plus

安装完成后,在项目里导入 ElementPlus,修改 main.js 如下:

import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'

const app = createApp(App)

app.use(ElementPlus)
app.mount('#app')

导入后,就可以启动项目了,执行以下命令:

看到以下界面说明项目成功启动了!后面就可以进入本教程的正式内容了。

kalacloud-卡拉云-初始化项目

Vue3 + Element Plus 生成动态表格

有一个场景是表格列并不是固定的,不能在前端写死,而是需要通过后端返回的数据进行动态渲染,比如后端返回了如下的表头数据:

tableHeader: {
  name: "姓名",
  birth: "生日",
  address: "地址",
  age: "年龄",
  phone: "电话",
}

这个对象中的 key 对应表格数据中的 propvalue 对应实际显示的 label,这样通过一个简单的对象,就可以连接表头和 表格body 之间的关系。然后还需要后端返回具体的表格数据:

tableData: [{
  name: '张三',
  date: '2016-05-02',
  address: '上海市普陀区金沙江路 1518 弄',
  age: 18,
  phone:"12345678910",
}, {
  date: '2016-05-04',
  name: '李四',
  address: '上海市普陀区金沙江路 1517 弄',
  age: 19,
  phone:"12345678911",
}, {
  date: '2016-05-01',
  name: '王五',
  address: '上海市普陀区金沙江路 1519 弄',
  age: 20,
  phone:"12345678912",
}, {
  date: '2016-05-03',
  name: '赵六',
  address: '上海市普陀区金沙江路 1516 弄',
  age: 21,
  phone:"12345678913",
}]

实现表格列动态渲染的功能,需要用到一个很关键的 vue 指令,那就是 v-forv-for 不仅可以遍历数据,也可以遍历对象:

<div v-for="(value, key) in object">
  {{ key }}: {{ value }}
</div>

这里我们就需要用到这个特性,来对 tableHeader 进行遍历,获取 keyvalue。基于以上讲解,现在我们具体实践一下如何实现表格列的动态渲染。在 components 目录中新建 DynamicTable.vue

<template>
  <div>
    <h2>Vue3 + Element plus 动态表格</h2>
    <el-table :data="tableData" style="width: 100%">
      <el-table-column
        :prop="index"
        :label="item"
        v-for="(item, index) in tableHeader"
        :key="index"
      >
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  name: "test",
  data() {
    return {
      tableHeader: {
        name: "姓名",
        birth: "生日",
        address: "地址",
        age: "年龄",
        phone: "电话",
      },
      tableData: [{
        name: '张三',
        address: '上海市普陀区金沙江路 1518 弄',
        birth: '2016-05-02',
        age: 18,
        phone: "12345678910",
      }, {
        name: '李四',
        birth: '2016-05-04',
        address: '上海市普陀区金沙江路 1517 弄',
        age: 19,
        phone: "12345678911",
      }, {
        name: '王五',
        birth: '2016-05-01',
        address: '上海市普陀区金沙江路 1519 弄',
        age: 20,
        phone: "12345678912",
      }, {
        name: '赵六',
        birth: '2016-05-03',
        address: '上海市普陀区金沙江路 1516 弄',
        age: 21,
        phone: "12345678913",
      }]
    }
  },
}
</script>

组件编写完成后,修改 App.vue,导入该组件即可:

<template>
  <DynamicTable />
</template>

<script>
import DynamicTable from './components/DynamicTable.vue'

export default {
  name: 'App',
  components: {
    DynamicTable
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

保存后页面会自动热更新,实现效果如下:

kalacloud-卡拉云-动态表格

这个只是比较基本的使用,如果某些列有一些定制需求,比如需要支持根据日期排序,这个时候可以对 tableHeader 进行改造,使 value 是一个对象,这样就可以携带更多的表头配置信息:

tableHeader: {
  name: {
    label: "姓名",
    sort: true,
  },
  birth: {
    label: "生日",
    sort: false,
  },
  address: {
    label: "地址",
    sort: false,
  },
  age: {
    label: "年龄",
    sort: true,
  },
  phone: {
    label: "电话",
    sort: false,
  }
},

然后再改造 el-table 如下:

<el-table-column
  :prop="index"
  :label="item.label"
  v-for="(item, index) in tableHeader"
  :sortable="item.sort"
  :key="index"
>

kalacloud-卡拉云-动态列排序

以上就实现了基于动态列的表头配置,这里的关键在于 tableHeader 的数据结构如何定义,可以把列信息都放在 tableHeader 中,然后再通过 v-for 循环列就可以渲染出对应的表格列。当然 tableHeader 也可以是一个数组,使用方法都是类似的,大家可以自己去尝试一下。

扩展阅读:《多款好用的 vue 表单设计器推荐测评

Vue3 + Element Plus 动态修改表格

基于以上的思路,我们还可以做的更多,比如动态添加指定行,指定列,或者删除指定行或者列等操作,都是使用相同的思路来实现。我们来具体实践一下,这里我们需要用到 @element-plus/icons-vue,先安装一下:

# NPM
npm install @element-plus/icons-vue
# Yarn
yarn add @element-plus/icons-vue

然后在 main.js 中导入:

import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

components 目录下新建 DynamicModifyTable.vue

<template>
  <div>
    <h2>Vue3 + Element plus 动态修改表格</h2>
    <h3>「卡拉云 - 极速搭建企业内部工具,十倍提升开发效率」</h3>
    <el-table :data="tableData" style="width: 100%">
      <el-table-column
        :prop="item.prop"
        :label="item.label"
        v-for="(item, index) in tableHeader"
        :key="item.prop"
      >
        <template #default="scope">
          <div
            v-show="item.editable || scope.row.editable"
            class="editable-row"
          >
            <template v-if="item.type === 'input'">
              <el-input
                size="small"
                v-model="scope.row[item.prop]"
                :placeholder="`请输入${item.label}`"
                @change="handleEdit(scope.$index, scope.row)"
              />
            </template>
            <template v-if="item.type === 'date'">
              <el-date-picker
                v-model="scope.row[item.prop]"
                type="date"
                value-format="YYYY-MM-DD"
                :placeholder="`请输入${item.label}`"
                @change="handleEdit(scope.$index, scope.row)"
              />
            </template>
          </div>
          <div
            v-show="!item.editable && !scope.row.editable"
            class="editable-row"
          >
            <span class="editable-row-span">{{ scope.row[item.prop] }}</span>
            <el-popover
              placement="right"
              :width="120"
              trigger="hover"
              content="this is content, this is content, this is content"
            >
              <template #reference>
                <el-icon class="icon" :size="18">
                  <Edit />
                </el-icon>
              </template>
              <div class="menu-list">
                <div
                  class="menu-item"
                  @click="prepend(scope.$index)"
                >
                  上方插入一行
                </div>
                <div
                  class="menu-item divider"
                  @click="append(scope.$index)"
                >
                  下方插入一行
                </div>
                <div class="menu-item" @click="deleteCurrentColumn(index)">
                  删除当前列
                </div>
                <div class="menu-item" @click="insertBefore(index)">
                  前方插入一列
                </div>
                <div class="menu-item" @click="insertAfter(index)">
                  后方插入一列
                </div>
              </div>
            </el-popover>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="操作">
        <template #default="scope">
          <el-button
            v-show="!scope.row.editable"
            size="small"
            @click="scope.row.editable = true"
            >编辑</el-button
          >
          <el-button
            v-show="scope.row.editable"
            size="small"
            type="success"
            @click="scope.row.editable = false"
            >确定</el-button
          >
          <el-button
            size="small"
            type="danger"
            @click="handleDelete(scope.$index)"
            >删除</el-button
          >
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
const item = {
  name: '',
  birth: '',
  province: "",
  city: "",
  address: '',
  phone: "",
}
const header = {
  prop: "key",
  label: "自定义",
  editable: false,
  type: "input",
}
export default {
  name: "DynamicModifyTable",
  data() {
    return {
      tableHeader: [
        {
          prop: "name",
          label: "姓名",
          editable: false,
          type: "input",
        },
        {
          prop: "birth",
          label: "生日",
          editable: false,
          type: "date"
        },
        {
          prop: "phone",
          label: "电话",
          editable: false,
          type: "input"
        },
        {
          prop: "province",
          label: "省份",
          editable: false,
          type: "input"
        },
        {
          prop: "city",
          label: "市区",
          editable: false,
          type: "input"
        },
        {
          prop: "address",
          label: "详细地址",
          editable: false,
          type: "input"
        }
      ],
      tableData: [{
        name: '张三',
        province: "上海市",
        city: "普陀区",
        address: "金沙江路 1518 弄",
        birth: '2016-05-02',
        phone: "12345678910",
      }, {
        name: '李四',
        birth: '2016-05-04',
        province: "上海市",
        city: "普陀区",
        address: '金沙江路 1517 弄',
        age: 19,
        phone: "12345678911",
      }, {
        name: '王五',
        birth: '2016-05-01',
        province: "上海市",
        city: "普陀区",
        address: '金沙江路 1519 弄',
        phone: "12345678912",
      }, {
        name: '赵六',
        birth: '2016-05-03',
        province: "上海市",
        city: "普陀区",
        address: '金沙江路 1516 弄',
        phone: "12345678913",
      }]
    }
  },
  methods: {
    handleEdit(row) {
      row.editable = true;
    },
    handleDelete(index) {
      this.tableData.splice(index, 1);
    },
    prepend(index) {
      item.editable = true
      this.tableData.splice(index, 0, item);
    },
    append(index) {
      item.editable = true
      this.tableData.splice(index + 1, 0, item);
    },
    deleteCurrentColumn(index) {
      this.tableHeader.splice(index, 1);
    },
    insertBefore(index) {
      header.editable = true;
      this.tableHeader.splice(index, 0, header);

Vue3 + Element Plus 创建动态多级表头

多级表头的实现比较简单,主要是通过 el-table-column 的嵌套来完成的,在 components 目录下新建 MultiHeaderTable.vue 文件:

<template>
  <div>
    <h2>Vue3 + Element plus 动态表格</h2>
    <el-table :data="tableData" style="width: 100%">
      <el-table-column
        :prop="item.prop"
        :label="item.label"
        v-for="(item, index) in tableHeader"
        :key="index"
      >
        <el-table-column
          :prop="child.prop"
          :label="child.label"
          v-for="(child, childIndex) in item.children"
          :key="childIndex"
        ></el-table-column>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  name: "MultiHeaderTable",
  data() {
    return {
      tableHeader: [
        {
          prop: "name",
          label: "姓名",
        },
        {
          prop: "birth",
          label: "生日",
        },
        {
          prop: "phone",
          label: "电话",
        },
        {
          label: "地址",
          children: [
            {
              prop: "province",
              label: "省份",
            },
            {
              prop: "city",
              label: "市区",
            },
            {
              prop: "address",
              label: "详细地址",
            }
          ]
        }
      ],
      tableData: [{
        name: '张三',
        province: "上海市",
        city: "普陀区",
        address: "金沙江路 1518 弄",
        birth: '2016-05-02',
        phone: "12345678910",
      }, {
        name: '李四',
        birth: '2016-05-04',
        province: "上海市",
        city: "普陀区",
        address: '金沙江路 1517 弄',
        age: 19,
        phone: "12345678911",
      }, {
        name: '王五',
        birth: '2016-05-01',
        province: "上海市",
        city: "普陀区",
        address: '金沙江路 1519 弄',
        phone: "12345678912",
      }, {
        name: '赵六',
        birth: '2016-05-03',
        province: "上海市",
        city: "普陀区",
        address: '金沙江路 1516 弄',
        phone: "12345678913",
      }]
    }
  },
}
</script>


对于 `tableHeader` 的定义,我们通过 `children` 字段来指定当前列的二级表头,但是会发现效果并不是我们预期的那样:

![kalacloud-卡拉云-错误演示动态多级表头](./images/04-kalacloud-vue3-element-plug-error.png "04-kalacloud-vue3-element-plug-error.png")

这是为什么呢?原来是因为 `el-table-column` 会检测内部是否还有 `el-table-column`,如果有的话,默认会显示内层的 `el-table-column`,但是在一级表头的情况下,内层 `el-table-column` 并没有值。所以我们需要简单修改一下代码,那就是通过 `v-if="item.children"` 来判断当前列是否有二级表头:


<el-table-column

:prop="child.prop"
:label="child.label"
v-for="(child, childIndex) in item.children"
:key="childIndex"


如果不这么做,那就只能渲染有二级表头的列,无法正常显示一级表头的数据, 最后的效果如下:

![kalacloud-卡拉云-动态多级表头](https://kalacloud.com/static/a602f459ea195bb911c07395f6469073/b8765/04-kalacloud-vue3-element-plus-muti-header.png)

扩展阅读:《[12款最棒的 Vue ui 组件库框架 推荐测评](https://kalacloud.com/blog/best-vue-ui-component-libraries/)》

## Vue3 + Element Plus 表格中单元格行合并

我们先来看下如何实现行合并,行合并或者是列合并,都需要用到 `el-table` 中 `span-method` 这个方法,在官方的例子中,是通过固定返回 `rowspan`,`colspan` 来实现行合并的:

const objectSpanMethod = ({
row,
column,
rowIndex, // 需要合并的开始行
columnIndex, // 需要合并的列
}) => {
if (columnIndex === 0) {

if (rowIndex % 2 === 0) {
  return {
    rowspan: 2, //合并的行数
    colspan: 1, //合并的列数
  }
} else {
  return {
    rowspan: 0,
    colspan: 0,
  }
}

}
}


但是在动态数据的场景下,这种方法就不适用了,因为前端的表格数据往往是后端通过接口返回的。比如我们有以下数据结构:

tableData: [{
name: '张三',
province: "上海市",
city: "普陀区",
address: "金沙江路 1518 弄",
birth: '2016-05-02',
phone: "12345678910",
}, {
name: '李四',
birth: '2016-05-02',
province: "上海市",
city: "普陀区",
address: '金沙江路 1517 弄',
age: 19,
phone: "12345678911",
}, {
name: '王五',
birth: '2016-05-03',
province: "上海市",
city: "普陀区",
address: '金沙江路 1519 弄',
phone: "12345678912",
}, {
name: '赵六',
birth: '2016-05-04',
province: "上海市",
city: "普陀区",
address: '金沙江路 1516 弄',
phone: "12345678913",
}, {
name: '孙七',
birth: '2016-05-04',
province: "上海市",
city: "普陀区",
address: '金沙江路 1516 弄',
phone: "12345678913",
}, {
name: '周八',
birth: '2016-05-04',
province: "上海市",
city: "普陀区",
address: '金沙江路 1516 弄',
phone: "12345678913",
}, {
name: '吴九',
birth: '2016-05-06',
province: "上海市",
city: "普陀区",
address: '金沙江路 1516 弄',
phone: "12345678913",
}]


我们的需求是把相同 `birth` 进行合并。在 `components` 目录下新建 `RowMergeTable.vue` 文件:

Vue3 + Element plus 动态行合并表格

this.spanArr = [];
return {
  tableHeader: [
    {
      prop: "birth",
      label: "生日",
    },
    {
      prop: "name",
      label: "姓名",
    },
    {
      prop: "phone",
      label: "电话",
    },
    {
      prop: "province",
      label: "省份",
    },
    {
      prop: "city",
      label: "市区",
    },
    {
      prop: "address",
      label: "详细地址",
    }
  ],
  tableData: [{
    name: '张三',
    province: "上海市",
    city: "普陀区",
    address: "金沙江路 1518 弄",
    birth: '2016-05-02',
    phone: "12345678910",
  }, {
    name: '李四',
    birth: '2016-05-02',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1517 弄',
    age: 19,
    phone: "12345678911",
  }, {
    name: '王五',
    birth: '2016-05-03',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1519 弄',
    phone: "12345678912",
  }, {
    name: '赵六',
    birth: '2016-05-04',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1520 弄',
    phone: "12345678913",
  }, {
    name: '孙七',
    birth: '2016-05-04',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1521 弄',
    phone: "12345678913",
  }, {
    name: '周八',
    birth: '2016-05-04',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1522 弄',
    phone: "12345678913",
  }, {
    name: '吴九',
    birth: '2016-05-06',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1523 弄',
    phone: "12345678913",
  }]
}

},
created() {

this.getSpanArr(this.tableData);

},
methods: {

getSpanArr(data) {
  for (var i = 0; i < data.length; i++) {
    if (i === 0) {
      this.spanArr.push(1);
      this.pos = 0
    } else {
      if (data[i].birth === data[i - 1].birth) {
        this.spanArr[this.pos] += 1;
        this.spanArr.push(0);
      } else {
        this.spanArr.push(1);
        this.pos = i;
      }
    }
  }
},
objectSpanMethod({ rowIndex, columnIndex }) {
  if (columnIndex === 0) {
    const _row = this.spanArr[rowIndex];
    const _col = _row > 0 ? 1 : 0;
    return {
      rowspan: _row,
      colspan: _col
    }
  }
}

}
}


上面的例子就实现了行合并的功能:

![kalacloud-卡拉云-动态行合并](https://kalacloud.com/static/8efdf694fe520cf8ef6d2ed466ac32fb/60708/05-kalacloud-vue3-element-plus-rowmerge.png)

因为表格的数据是动态的,所以我们需要事先通过计算,来得知哪些行是需要合并的,这里就是通过 `getSpanArr` 方法来实现的,全局维护了一个 `spanArr` 变量,用于记录每一行需要合并的数字,`pos` 是 `spanArr` 的索引,这样就可以根据索引来动态设置需要合并的行树。当 `i === 0`,说明是第一行数据,向 `spanArr` 数组中 `push` 1,当 `i !== 0`,此时就需要比较当前行与前一行数据的 `birth` 是否相等,如果相等,则利用索引,修改当前行需要合并的行数。

`objectSpanMethod` 方法,在 `el-table` 渲染每一行数据的时候都会执行,这样就可以通过 `rowIndex` 来获取每一行需要合并的行数信息,来实现行合并的功能。

那么如何实现多行合并?其实也是一样的思路,通过 `spanMap` 可以存储多个列的行合并信息。在 `components` 下新建 `MultiRowMergeTable.vue`:

Vue3 + Element plus 动态多行合并表格

this.spanMap = {};
this.mergedColumns = ["birth", "province", "city"]
return {
  tableHeader: [
    {
      prop: "birth",
      label: "生日",
    },
    {
      prop: "name",
      label: "姓名",
    },
    {
      prop: "phone",
      label: "电话",
    },
    {
      prop: "province",
      label: "省份",
    },
    {
      prop: "city",
      label: "市区",
    },
    {
      prop: "address",
      label: "详细地址",
    }
  ],
  tableData: [{
    name: '张三',
    province: "上海市",
    city: "普陀区",
    address: "金沙江路 1518 弄",
    birth: '2016-05-02',
    phone: "12345678910",
  }, {
    name: '李四',
    birth: '2016-05-02',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1517 弄',
    age: 19,
    phone: "12345678911",
  }, {
    name: '王五',
    birth: '2016-05-03',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1519 弄',
    phone: "12345678912",
  }, {
    name: '赵六',
    birth: '2016-05-04',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1520 弄',
    phone: "12345678913",
  }, {
    name: '孙七',
    birth: '2016-05-04',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1521 弄',
    phone: "12345678913",
  }, {
    name: '周八',
    birth: '2016-05-04',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1522 弄',
    phone: "12345678913",
  }, {
    name: '吴九',
    birth: '2016-05-06',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1523 弄',
    phone: "12345678913",
  }]
}

},
created() {

this.getSpanArr(this.tableData);

},
methods: {

getSpanArr(data) {
  for (var i = 0; i < data.length; i++) {
    if (i === 0) {
      this.mergedColumns.forEach(column => {
        this.spanMap[column] = {
          spanArr: [1],
          pos: 0
        }
      })
    } else {
      this.mergedColumns.forEach(column => {
        if (data[i][column] === data[i - 1][column]) {
          this.spanMap[column].spanArr[this.spanMap[column].pos] += 1;
          this.spanMap[column].spanArr.push(0)
        } else {
          this.spanMap[column].spanArr.push(1);
          this.spanMap[column].pos = i;
        }
      })
    }
  }
},
objectSpanMethod({ column, rowIndex }) {
  if (this.spanMap[column.property]) {
    const _row = this.spanMap[column.property].spanArr[rowIndex];
    const _col = _row > 0 ? 1 : 0;
    return {
      rowspan: _row,
      colspan: _col
    }
  }
}

}
}


实现效果如下:

![kalacloud-卡拉云-动态多行合并](https://kalacloud.com/static/b02bf3557a64475277e78b69657beee1/b8765/06-kalacloud-vue3-element-plus-mutil-row.png)

动态多行合并的需求往往更常见,需要把每一列中,相同的数据进行合并,都可以参照这个思路来实现。

扩展阅读:《[Vue + Node.js 全栈开发实战教程 - 手把手教你搭建「文件上传」管理后台](https://kalacloud.com/blog/vue-axios-multiple-node-express-file-upload/)》

## Vue3 + Element Plus 表格中单元格列合并

接下来,我们来看下如何实现列的合并,其实思路是和行合并类似的,也需要用到 `span-method` 这个方法,唯一不同的在于,列合并需要处理被合并列的原始数据,否则被合并列的原始数据会填充到合并之后的表格里,这样说可能有点抽象,我们写来写一个例子,在 components 下新建 ColumnMergeTable.vue:

Vue3 + Element plus 动态表格列合并

return {
  tableHeader: [
    {
      prop: "birth",
      label: "生日",
    },
    {
      prop: "name",
      label: "姓名",
    },
    {
      prop: "phone",
      label: "电话",
    },
    {
      prop: "province",
      label: "省份",
    },
    {
      prop: "city",
      label: "市区",
    },
    {
      prop: "address",
      label: "详细地址",
    }
  ],
  tableData: [{
    name: '张三',
    province: "上海市",
    city: "普陀区",
    address: "金沙江路 1518 弄",
    birth: '2016-05-02',
    phone: "12345678910",
  }, {
    name: '李四',
    birth: '2016-05-02',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1517 弄',
    age: 19,
    phone: "12345678911",
  }, {
    name: '王五',
    birth: '2016-05-03',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1519 弄',
    phone: "12345678912",
  }, {
    name: '赵六',
    birth: '2016-05-04',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1520 弄',
    phone: "12345678913",
  }, {
    name: '孙七',
    birth: '2016-05-04',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1521 弄',
    phone: "12345678913",
  }, {
    name: '周八',
    birth: '2016-05-04',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1522 弄',
    phone: "12345678913",
  }, {
    name: '吴九',
    birth: '2016-05-06',
    province: "上海市",
    city: "普陀区",
    address: '金沙江路 1523 弄',
    phone: "12345678913",
  }]
}

},
methods: {

objectSpanMethod({ rowIndex, columnIndex }) {
  // 隐藏第二行或者第三行的列
  if (rowIndex === 1 || rowIndex === 2) {
    // 合并第二行
    if (columnIndex === 1) {
      // 从第二列开始
      return [1, 3]
      //或者返回如下形式也可以
      // return {
      //    rowspan: 1,
      //    colspan: 3
      //  }
      // 这里的 else if 即使用来处理被合并列的原始数据的情况,需要隐藏原始单元格
    } else if (columnIndex === 2 || columnIndex === 3) {
      return [0, 0]
    }
  }
}

}
}


可以看出来,列合并其实比行合并简单一些,返回一个数组更容易理解一些,数组的第一项表示合并的起始列,第二项表示合并的终止列,其区间的所有列都会合并成一列,被合并的列还需要通过 \[0, 0\] 来隐藏对应的单元格,这个是和行合并不同的地方。

**扩展阅读:**《[Vue echarts 使用教程](https://kalacloud.com/blog/vue-echarts-tutorial/)》

## Vue3 + Element Plus 动态表格源代码

本教程所写源代码可在我们的 [github](https://github.com/kalacloudCode/how-to-build-dynamic-table-in-vue-element-plus) 上找到。

## 动态表格与卡拉云

本文详细讲解如何 Vue3 + Element Plus 中如何创建动态表格的问题。其实如果你根本不想处理复杂的前端问题,完全可以使用卡拉云来处理前端表格,卡拉云内置表格组件,直接鼠标拖拽即可生成,不仅可以处理动态表格,内容实时编辑以及表格中展示图片等功能,还有强大的过滤筛选、数据导出功能。

 ![卡拉云内置表格](https://kalacloud.com/static/b9481a4b63d08768c2658fa50e81cd84/42be1/07-kalacloud.jpg)

卡拉云可帮你快速搭建企业内部工具,下图为使用卡拉云搭建的内部广告投放监测系统,无需懂前端,仅需拖拽组件,10 分钟搞定。你也可以快速搭建一套属于你的后台管理工具。

![卡拉云企业内部工具](https://kalacloud.com/static/b9481a4b63d08768c2658fa50e81cd84/8369b/09-kalacloud.webp)

[卡拉云](https://kalacloud.com/)是新一代低代码开发平台,与前端框架 Vue、React等相比,卡拉云的优势在于不用首先搭建开发环境,直接注册即可开始使用。开发者完全不用处理任何前端问题,只需简单拖拽,即可快速生成所需组件,可一键接入常见数据库及 API,根据引导简单几步打通前后端,数周的开发时间,缩短至 1 小时。立即免费[试用卡拉云](https://my.kalacloud.com/signup)。

**扩展阅读:**

-   [Vue form 表单异步验证终极教程](https://kalacloud.com/blog/vue-form-validate-tutorial/)
-   [最好用的 6 款 MongoDB GUI 管理工具横向测评](https://kalacloud.com/blog/best-mongodb-gui-tools/)
-   [5 款最棒的 Vue UI 移动端组件库 - 特别针对国内使用场景推荐](https://kalacloud.com/blog/best-vue-mobile-ui-component-libraries/)
-   [顶级好用的 5 款 Vue table 表格组件测评与推荐](https://kalacloud.com/blog/best-vue-data-table-grid/)
相关文章
|
2天前
|
JavaScript API 数据处理
vue3使用pinia中的actions,需要调用接口的话
通过上述步骤,您可以在Vue 3中使用Pinia和actions来管理状态并调用API接口。Pinia的简洁设计使得状态管理和异步操作更加直观和易于维护。无论是安装配置、创建Store还是在组件中使用Store,都能轻松实现高效的状态管理和数据处理。
16 3
|
28天前
|
前端开发 JavaScript 测试技术
Vue3中v-model在处理自定义组件双向数据绑定时,如何避免循环引用?
Web 组件化是一种有效的开发方法,可以提高项目的质量、效率和可维护性。在实际项目中,要结合项目的具体情况,合理应用 Web 组件化的理念和技术,实现项目的成功实施和交付。通过不断地探索和实践,将 Web 组件化的优势充分发挥出来,为前端开发领域的发展做出贡献。
32 8
|
27天前
|
存储 JavaScript 数据管理
除了provide/inject,Vue3中还有哪些方式可以避免v-model的循环引用?
需要注意的是,在实际开发中,应根据具体的项目需求和组件结构来选择合适的方式来避免`v-model`的循环引用。同时,要综合考虑代码的可读性、可维护性和性能等因素,以确保系统的稳定和高效运行。
30 1
|
27天前
|
JavaScript
Vue3中使用provide/inject来避免v-model的循环引用
`provide`和`inject`是 Vue 3 中非常有用的特性,在处理一些复杂的组件间通信问题时,可以提供一种灵活的解决方案。通过合理使用它们,可以帮助我们更好地避免`v-model`的循环引用问题,提高代码的质量和可维护性。
36 1
|
1月前
|
JavaScript API 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
7天前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
1月前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
41 1
vue学习第一章
|
1月前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
30 1
|
1月前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
38 1
vue学习第四章
|
1月前
|
JavaScript 前端开发 算法
vue学习第7章(循环)
欢迎来到瑞雨溪的博客,一名热爱JavaScript和Vue的大一学生。本文介绍了Vue中的v-for指令,包括遍历数组和对象、使用key以及数组的响应式方法等内容,并附有综合练习实例。关注我,将持续更新更多优质文章!🎉🎉🎉
25 1
vue学习第7章(循环)