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监听是因为会导致互相嵌套,导致选择逻辑不能如预期那样展现。

浙公网安备 33010602011771号