vue3+elementplus动态渲染表格

笔记记录:

有这么一个需求,用户可以自定义选择表格哪些列显示,因此作此记录。

 

首先是模板内:

 1               <el-table
 2                   :header-cell-class-name="cellClass"
 3                   :height="tableHeight"
 4                   ref="tableRef"
 5                   :data="state.dataList"
 6                   v-loading="state.loading"
 7                   :header-cell-style="tableStyle.headerCellStyle"
 8               >
 9                   <el-table-column type="selection" width="55" :show-overflow-tooltip="false" align="center" />
10                  <el-table-column type="index" label="序号" width="60" align="center" />
11                  <template v-for="item in allColumns" :key="item.key">
12                      <el-table-column v-if="item.show" :prop="item.key" :label="item.header" :align="item.align" :width="item.width_T">
13                          <template #default="scope">
14                              <component :is="item.render" :scope="scope"></component>
15                          </template>
16                      </el-table-column>
17                  </template>
18                  <el-table-column prop="" label="" width="100" />
19              </el-table>
20             <el-popover placement="bottom" width="180" :visible="columnsVisible">
21                         <template #reference>
22                             <div class="button last" @click="columnsVisible = !columnsVisibl">

23 <img src="../../../assets/img/newIcon/列表展示项设.png" />
24                             </div>
25                         </template>
26                         <template #default>
27                             <div class="columnList">
28                                 <el-checkbox v-model="allColumnsSelected" label="全选" @change="changeAllSelected"></el-checkbox>
29                                 <el-scrollbar height="240px">
30                                     <el-checkbox-group v-model="selectedColumns">
31                                         <el-checkbox v-for="item in allColumns" :key="item.key" :value="item.key" :label="item.header"></el-checkbox>
32                                     </el-checkbox-group>
33                                 </el-scrollbar>
34                                 <div class="confirmButton">
35                                     <el-button type="primary" @click="selectShowColumns">确定</el-button>
36                                 </div>
37                             </div>
38                         </template>
39                     </el-popover>

popover是用来选择哪些字段要显示的控制器

因为v-for和v-if不能同时使用,所以通过嵌套一层template来控制表格列的显示与否;

然后是插槽,动态渲染时某些自定义样式譬如字体颜色,数据格式化等。如果插槽内的组件也想要自定义的话(譬如字体颜色,有的想要红色有的绿色)可以提供对应属性譬如 

<component :is="item.render" :scope="scope" :color="item.color"></component>

不用担心,其它没有接受该属性的组件不会因此受到影响(譬如需要格式化的组件)

 

接下来是js部分:

 1 //所有表格字段
 2 const allColumns = ref([
 3     { header: '财务日期', key: 'findate', width_T: 120, align: 'center', show: true },
 4     { header: '班次', key: 'shiftname', width_T: 80, align: 'center', show: true },
 5     { header: '班次编号', key: 'shiftno', width_T: 90, align: 'center', show: true },
 6     …………
 7     { header: '备注', key: 'handmoneynote', width_T: 1000, align: 'left', render: shallowRef(colorColumn), show: true },
 8 ]);
 9 //全选按钮
10 const allColumnsSelected = ref(true);
11 //当前选择的列
12 const selectedColumns = ref(allColumns.value.map((item) => item.key));
13 //下拉框可见性
14 const columnsVisible = ref(false);
15 const selectShowColumns = () => {
16     if (selectedColumns.value.length === 0) {
17         useMessage().error('请至少选择一列!');
18         return false;
19     } else {
20         allColumns.value.forEach((col) => (col.show = false));
21         selectedColumns.value.forEach((item) => {
22             for (let n = 0; n < allColumns.value.length; n++) {
23                 if (item === allColumns.value[n].key) {
24                     allColumns.value[n].show = true;
25                     return;
26                 }
27             }
28         });
29     }
30     columnsVisible.value = false;
31 };
32 watch(
33     () => selectedColumns.value.length,
34     (val) => {
35         allColumnsSelected.value = val === allColumns.value.length;
36     }
37 );
38 //全选时直接选择所有
39 const changeAllSelected = (val) => {
40     selectedColumns.value = val ? allColumns.value.map((item) => item.key) : [];
41 };

因为是要动态渲染,所以allColumns需要定义为响应式的,否则内部属性改变时,表格不会动态读取其属性值而更改自身字段的可视性。

同时,用了setup语法糖,因此引入的组件可以直接使用,无需注册。而因为该组件被包裹在响应式变量中,因此为了避免不必要的性能浪费,请加上 shallowRef(componentName) 不让vue进行深层次的解析(至少如果你不加的话,会有警告,以及vue文档里这么推荐解决的)响应式 API:核心 | Vue.js

下面不用两个watch监听是因为会导致互相嵌套,导致选择逻辑不能如预期那样展现。

 

posted @ 2025-03-06 11:21  RicardoX3  阅读(627)  评论(0)    收藏  举报