踩坑记28 el-table default-sort属性 sort() 排序 & toggleRowExpansion 折叠 展开 & el-icon 导入报错 组件名与html元素名重复

本文详细介绍了在Element-Plus库中使用el-table进行自动和手动排序的实践,包括default-sort属性的使用、手动排序函数sortData的实现,以及解决排序问题的策略。同时,针对表格的展开与折叠功能,展示了如何使用toggleRowExpansion方法实现一键展开/折叠。此外,还提到了el-icon组件导入时的命名冲突问题及其解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2021.9.23

坑86(el-table、default-sort、排序):el-table 表格的自动/手动排序。自动:el-table自带能力。手动:自写排序函数处理事件。

el-table自动排序参考文档:  Table 表格 | ElementPlus (element-plus.org)   排序Sorting部分。

在表格上设置 default-sort 属性即可自动排序,类型为对象。prop 排序属性,order 排序方式,类型都为字符串。

// descending 降序  升序(默认) 
// 经实验发现,非descending一律升序
:default-sort='{prop:"sortCode", order:"ascending"}'

!注意:如果部分数据无排序prop字段,则整体排序会混乱,甚至会多出重复数据。

另外在列上设置 sortable 属性为true时,对应列会展示上下箭头标签,点击可控制升序/降序/原序。

尝试隐藏排序字段列(失败):

1、v-show='false'无效,依然显示;

2、v-if='false'则直接不渲染,相当于没有该列数据,default-sort设置的排序将不会生效

参考:element el-table列 显示隐藏的问题 - 收破烂的小伙子 - 博客园 (cnblogs.com)

 element-ui表格组件table实现列的动态显示与隐藏 - 简书 (jianshu.com) v-if、v-for方案,隐藏列(没渲染)无法用于排序。

3、class-name方案:参考 请问一下elementui使用el-table怎么隐藏列 - SegmentFault 思否   使用class-name,其中table的table-layout属性添加与否未发现区别(scoped的style需要用到深度选择器)。在列上设置类名class-name,会传递给该列包括表头在内的每一个单元格,scoped的style需要用到深度选择器

class-name='notShow'

:deep(.notShow){
    display: none !important;
}

class-name方案存在问题:

1、若该列设置了宽度属性(在template里,style设置加important也没有效果),则该宽度会由其右侧一列延用,比如排序列设置较窄,width='60',则其右侧的名称列会变窄;

2、最右侧会留大片空白,因为各列宽度是基于排序列存在时的情况计算的。

考虑了其他table插件:Handsontable 收费,功能较全  Handsontable--在线Excel表格 - 简书 (jianshu.com)

手动排序:基于以上种种坑,最后还是写了一个排序函数 sortData(data,sign) 来实现排序。data为数据数组,sign为排序属性,此次默认采用Number类型的属性。在向el-table传数据前调用即可。

2021.10.26更新排序函数 sortData(data,sign),解决父项是单个则无法通过Array.sort排序多个子项的问题。采用的方法是使用Array.map确保访问到每个子项。

// el-table调用
<el-table :data='sortData(infoTable,"sortCode")' row-key="itemId" >
...
// 排序(2021.10.26更新),sign需为Number
export function sortData(data,sign){
    data=data.sort((a,b)=>{
        if( typeof a[sign] ==='number' && typeof b[sign] ==='number'){
            return a[sign]-b[sign]  // 升序排列,小到大
        }else if(typeof a[sign] !=='number' && typeof b[sign] !=='number'){
            return 0  // 不变
        }else if(typeof a[sign] !=='number'){
            return 1  // a在后
        }else{
            return -1  // b在后
        }
    }).map(item=>{
        // 排序子项
        if(item.children && item.children.length>0){
            item.children=sortData(item.children,sign)
        }
        return item
    })
    return data
}


/*
// 排序(原版,有bug),sign需为Number
export function sortData(data,sign){
    // 使用Array.sort存在问题:
    // 当外层只有一项时,排序函数不会被调用,也就不会排序内部的多个子项
    data.sort((a,b)=>{
        if(a.children && a.children.length>0){
            sortData(a.children,sign)
        }
        if(b.children && b.children.length>0){
            sortData(b.children,sign)
        }


        if( typeof a[sign] ==='number' && typeof b[sign] ==='number'){
            return a[sign]-b[sign]  // 升序排列,小到大
        }else if(typeof a[sign] !=='number' && typeof b[sign] !=='number'){
            return 0  // 不变
        }else if(typeof a[sign] !=='number'){
            return 1  // a在后
        }else{
            return -1  // b在后
        }
    })
    return data
}
*/

坑87(el-table、折叠、展开):一键展开/折叠el-table。通过调用el-table的 toggleRowExpansion(row,isExpand) 方法实现。row 为行数据,isExpand 为是否展开。具体代码如下:

<el-button @click='handletotalExpand()'>{{isExpand?'折叠':'展开'}}</el-button>
...
const state=reactive({
    isExpand:false,
})
// ref绑定到对应el-table
let infoTableRef=ref(null)

// 工具函数,实现el-table展开/折叠
// data为表格元素实例的数据数组,table为表格元素,isExpand是否展开
const expandTable=(data,table,isExpand)=>{
    data.map(item=>{
        table.toggleRowExpansion(item,isExpand)
        if(item.children && item.children.length>0){
            expandTable(item.children,table,isExpand)
        }
    })
}

// 处理展开/折叠
const handletotalExpand=()=>{
    state.isExpand=!state.isExpand
        // 调用工具函数
    expandTable(infoTableRef.value.data,infoTableRef.value,state.isExpand)
}

return {
    handletotalExpand,
    infoTableRef,
}

参考:elementUI中el-table树形与el-tree树形结构的一键折叠与展开_cabinx的博客-优快云博客

坑88(el-icon、导入报错):导入el-icon的switch图标时报错如下:

Do not use built-in or reserved HTML elements as component id: switch

// 不要使用内置或保留的HTML元素作为组件id

报错原因是switch图标导入组件名称设置为switch与html元素名重复了。更改导入名称即可,代码如下:

// 将switch图标的组件名称改为i-switch

// 原先设定的组件名称是switch,会报错

app.component('i-switch',Switch) 

参考:Vue报错'Do not use built-in or reserved HTML elements as component id:解决方法_S筱潇S四维Smile-优快云博客  

聊聊 Vue 组件命名那些事 - CNode技术社区 (cnodejs.org)

by 莫得感情踩坑机(限定)

&lt;template&gt; &lt;div class=&quot;app-container&quot;&gt; &lt;el-form :model=&quot;queryParams&quot; ref=&quot;queryForm&quot; size=&quot;small&quot; :inline=&quot;true&quot; v-show=&quot;showSearch&quot; label-width=&quot;68px&quot;&gt; &lt;el-form-item label=&quot;编号&quot; prop=&quot;number&quot;&gt; &lt;el-input v-model=&quot;queryParams.number&quot; placeholder=&quot;请输入编号&quot; clearable @keyup.enter.native=&quot;handleQuery&quot; /&gt; &lt;/el-form-item&gt; &lt;el-form-item label=&quot;&quot; prop=&quot;name&quot;&gt; &lt;el-input v-model=&quot;queryParams.name&quot; placeholder=&quot;请输入&quot; clearable @keyup.enter.native=&quot;handleQuery&quot; /&gt; &lt;/el-form-item&gt; &lt;el-form-item label=&quot;状态&quot; prop=&quot;status&quot;&gt; &lt;el-select v-model=&quot;queryParams.status&quot; placeholder=&quot;请选择状态&quot; clearable&gt; &lt;el-option v-for=&quot;dict in dict.type.mdm_common_status_list&quot; :key=&quot;dict.value&quot; :label=&quot;dict.label&quot; :value=&quot;dict.value&quot; /&gt; &lt;/el-select&gt; &lt;/el-form-item&gt; &lt;el-form-item&gt; &lt;el-button type=&quot;primary&quot; icon=&quot;el-icon-search&quot; size=&quot;mini&quot; @click=&quot;handleQuery&quot;&gt;搜索&lt;/el-button&gt; &lt;el-button icon=&quot;el-icon-refresh&quot; size=&quot;mini&quot; @click=&quot;resetQuery&quot;&gt;重置&lt;/el-button&gt; &lt;/el-form-item&gt; &lt;/el-form&gt; &lt;el-row :gutter=&quot;10&quot; class=&quot;mb8&quot;&gt; &lt;el-col :span=&quot;1.5&quot;&gt; &lt;el-button type=&quot;primary&quot; plain icon=&quot;el-icon-plus&quot; size=&quot;mini&quot; @click=&quot;handleAdd&quot; v-hasPermi=&quot;[&#39;mdm:mdmMaterialType:add&#39;]&quot; &gt;新增&lt;/el-button&gt; &lt;/el-col&gt; &lt;el-col :span=&quot;1.5&quot;&gt; &lt;el-button type=&quot;info&quot; plain icon=&quot;el-icon-upload2&quot; size=&quot;mini&quot; @click=&quot;handleImport&quot; v-hasPermi=&quot;[&#39;mdm:mdmMaterialType:import&#39;]&quot; &gt;导入&lt;/el-button&gt; &lt;/el-col&gt; &lt;el-col :span=&quot;1.5&quot;&gt; &lt;el-button type=&quot;warning&quot; plain icon=&quot;el-icon-download&quot; size=&quot;mini&quot; @click=&quot;handleExport&quot; v-hasPermi=&quot;[&#39;mdm:mdmMaterialType:export&#39;]&quot; &gt;导出&lt;/el-button&gt; &lt;/el-col&gt; &lt;el-col :span=&quot;1.5&quot;&gt; &lt;el-button type=&quot;info&quot; plain icon=&quot;el-icon-sort&quot; size=&quot;mini&quot; @click=&quot;toggleExpandAll&quot; &gt;展开/折叠&lt;/el-button&gt; &lt;/el-col&gt; &lt;right-toolbar :showSearch.sync=&quot;showSearch&quot; @queryTable=&quot;getList&quot;&gt;&lt;/right-toolbar&gt; &lt;/el-row&gt; &lt;el-table v-if=&quot;refreshTable&quot; v-loading=&quot;loading&quot; :data=&quot;mdmMaterialTypeList&quot; row-key=&quot;id&quot; :default-expand-all=&quot;isExpandAll&quot; :tree-props=&quot;{children: &#39;children&#39;, hasChildren: &#39;hasChildren&#39;}&quot; &gt; &lt;el-table-column label=&quot;&quot; align=&quot;left&quot; prop=&quot;name&quot; /&gt; &lt;el-table-column label=&quot;编号&quot; prop=&quot;number&quot; /&gt; &lt;!-- &lt;el-table-column label=&quot;父ID&quot; align=&quot;center&quot; prop=&quot;parentId&quot; /&gt;--&gt; &lt;el-table-column label=&quot;状态&quot; align=&quot;center&quot; prop=&quot;status&quot;&gt; &lt;template slot-scope=&quot;scope&quot;&gt; &lt;dict-tag :options=&quot;dict.type.mdm_common_status_list&quot; :value=&quot;scope.row.status&quot;/&gt; &lt;/template&gt; &lt;/el-table-column&gt; &lt;el-table-column label=&quot;创建时间&quot; align=&quot;center&quot; prop=&quot;createTime&quot; /&gt; &lt;!-- &lt;el-table-column label=&quot;图标&quot; align=&quot;center&quot; prop=&quot;icon&quot; /&gt;--&gt; &lt;!-- &lt;el-table-column label=&quot;命规则&quot; align=&quot;center&quot; prop=&quot;namingrule&quot; /&gt;--&gt; &lt;el-table-column label=&quot;操作&quot; align=&quot;center&quot; class-name=&quot;small-padding fixed-width&quot;&gt; &lt;template slot-scope=&quot;scope&quot;&gt; &lt;el-button size=&quot;mini&quot; type=&quot;text&quot; icon=&quot;el-icon-edit&quot; @click=&quot;handleUpdate(scope.row)&quot; v-hasPermi=&quot;[&#39;mdm:mdmMaterialType:edit&#39;]&quot; &gt;修改&lt;/el-button&gt; &lt;el-button size=&quot;mini&quot; type=&quot;text&quot; icon=&quot;el-icon-plus&quot; @click=&quot;handleAdd(scope.row)&quot; v-hasPermi=&quot;[&#39;mdm:mdmMaterialType:add&#39;]&quot; &gt;新增&lt;/el-button&gt; &lt;el-button size=&quot;mini&quot; type=&quot;text&quot; icon=&quot;el-icon-delete&quot; @click=&quot;handleDelete(scope.row)&quot; v-hasPermi=&quot;[&#39;mdm:mdmMaterialType:remove&#39;]&quot; &gt;删除&lt;/el-button&gt; &lt;/template&gt; &lt;/el-table-column&gt; &lt;/el-table&gt; &lt;!-- 添加或修改物料类型对话框 --&gt; &lt;el-dialog :title=&quot;title&quot; :visible.sync=&quot;open&quot; width=&quot;500px&quot; append-to-body&gt; &lt;el-form ref=&quot;form&quot; :model=&quot;form&quot; :rules=&quot;rules&quot; label-width=&quot;80px&quot;&gt; &lt;el-form-item label=&quot;&quot; prop=&quot;name&quot;&gt; &lt;el-input v-model=&quot;form.name&quot; placeholder=&quot;请输入&quot; /&gt; &lt;/el-form-item&gt; &lt;el-form-item label=&quot;编号&quot; prop=&quot;number&quot;&gt; &lt;el-input v-model=&quot;form.number&quot; placeholder=&quot;请输入编号&quot; /&gt; &lt;/el-form-item&gt; &lt;el-form-item label=&quot;父ID&quot; prop=&quot;parentId&quot;&gt; &lt;treeselect v-model=&quot;form.parentId&quot; :options=&quot;mdmMaterialTypeOptions&quot; :normalizer=&quot;normalizer&quot; placeholder=&quot;请选择父ID&quot; /&gt; &lt;/el-form-item&gt; &lt;el-form-item label=&quot;图标&quot; prop=&quot;icon&quot;&gt; &lt;el-input v-model=&quot;form.icon&quot; placeholder=&quot;请输入图标&quot; /&gt; &lt;/el-form-item&gt; &lt;el-form-item label=&quot;命规则&quot; prop=&quot;namingrule&quot;&gt; &lt;el-input v-model=&quot;form.namingrule&quot; placeholder=&quot;请输入命规则&quot; /&gt; &lt;/el-form-item&gt; &lt;el-form-item label=&quot;状态&quot; prop=&quot;status&quot;&gt; &lt;el-radio-group v-model=&quot;form.status&quot;&gt; &lt;el-radio v-for=&quot;dict in dict.type.mdm_common_status_list&quot; :key=&quot;dict.value&quot; :label=&quot;dict.value&quot; &gt;{{dict.label}}&lt;/el-radio&gt; &lt;/el-radio-group&gt; &lt;/el-form-item&gt; &lt;/el-form&gt; &lt;div slot=&quot;footer&quot; class=&quot;dialog-footer&quot;&gt; &lt;el-button type=&quot;primary&quot; @click=&quot;submitForm&quot;&gt;确 定&lt;/el-button&gt; &lt;el-button @click=&quot;cancel&quot;&gt;取 消&lt;/el-button&gt; &lt;/div&gt; &lt;/el-dialog&gt; &lt;!-- 用户导入对话框 --&gt; &lt;el-dialog :title=&quot;upload.title&quot; :visible.sync=&quot;upload.open&quot; width=&quot;400px&quot; append-to-body&gt; &lt;el-upload ref=&quot;upload&quot; :limit=&quot;1&quot; accept=&quot;.xlsx, .xls&quot; :headers=&quot;upload.headers&quot; :action=&quot;upload.url + &#39;?updateSupport=&#39; + upload.updateSupport&quot; :disabled=&quot;upload.isUploading&quot; :on-progress=&quot;handleFileUploadProgress&quot; :on-success=&quot;handleFileSuccess&quot; :auto-upload=&quot;false&quot; drag &gt; &lt;i class=&quot;el-icon-upload&quot;&gt;&lt;/i&gt; &lt;div class=&quot;el-upload__text&quot;&gt;将文件拖到此处,或&lt;em&gt;点击上传&lt;/em&gt;&lt;/div&gt; &lt;div class=&quot;el-upload__tip text-center&quot; slot=&quot;tip&quot;&gt; &lt;div class=&quot;el-upload__tip&quot; slot=&quot;tip&quot;&gt; &lt;el-checkbox v-model=&quot;upload.updateSupport&quot; /&gt; 是否更新已经存在的用户数据 &lt;/div&gt; &lt;span&gt;仅允许导入xls、xlsx格式文件。&lt;/span&gt; &lt;el-link type=&quot;primary&quot; :underline=&quot;false&quot; style=&quot;font-size:12px;vertical-align: baseline;&quot; @click=&quot;importTemplate&quot;&gt;下载模板&lt;/el-link&gt; &lt;/div&gt; &lt;/el-upload&gt; &lt;div slot=&quot;footer&quot; class=&quot;dialog-footer&quot;&gt; &lt;el-button type=&quot;primary&quot; @click=&quot;submitFileForm&quot;&gt;确 定&lt;/el-button&gt; &lt;el-button @click=&quot;upload.open = false&quot;&gt;取 消&lt;/el-button&gt; &lt;/div&gt; &lt;/el-dialog&gt; &lt;/div&gt; &lt;/template&gt; &lt;script&gt; import { listMdmMaterialType, getMdmMaterialType, delMdmMaterialType, addMdmMaterialType, updateMdmMaterialType } from &quot;@/api/mdm/mdmMaterialType&quot;; import Treeselect from &quot;@riophae/vue-treeselect&quot;; import &quot;@riophae/vue-treeselect/dist/vue-treeselect.css&quot;; import { getToken } from &quot;@/utils/auth&quot;; export default { name: &quot;MdmMaterialType&quot;, dicts: [&#39;mdm_common_status_list&#39;], components: { Treeselect }, data() { return { // 遮罩层 loading: true, // 显示搜索条件 showSearch: true, // 物料类型表格数据 mdmMaterialTypeList: [], // 物料类型树选项 mdmMaterialTypeOptions: [], // 弹出层标题 title: &quot;&quot;, // 是否显示弹出层 open: false, // 是否展开,默认全部展开 isExpandAll: true, // 重新渲染表格状态 refreshTable: true, // 查询参数 queryParams: { number: null, name: null, parentId: null, status: null, icon: null, namingrule: null }, // 表单参数 form: {}, // 表单校验 rules: { number: [ { required: true, message: &quot;编号不能为空&quot;, trigger: &quot;blur&quot; } ], parentId: [ { required: true, message: &quot;父ID不能为空&quot;, trigger: &quot;blur&quot; } ], }, // 导入参数 upload: { // 是否显示弹出层(导入) open: false, // 弹出层标题(导入) title: &quot;&quot;, // 是否禁用上传 isUploading: false, // 是否更新已经存在的用户数据 updateSupport: 0, // 设置上传的请求头部 headers: { Authorization: &quot;Bearer &quot; + getToken() }, // 上传的地址 url: process.env.VUE_APP_BASE_API + &quot;/mdm/mdmMaterialType/importData&quot; }, }; }, created() { this.getList(); }, methods: { /** 查询物料类型列表 */ getList() { this.loading = true; listMdmMaterialType(this.queryParams).then(response =&gt; { this.mdmMaterialTypeList = this.handleTree(response.data, &quot;id&quot;, &quot;parentId&quot;); this.loading = false; }); }, /** 转换物料类型数据结构 */ normalizer(node) { if (node.children &amp;&amp; !node.children.length) { delete node.children; } return { id: node.id, label: node.name, children: node.children }; }, /** 查询物料类型下拉树结构 */ getTreeselect() { listMdmMaterialType().then(response =&gt; { this.mdmMaterialTypeOptions = []; const data = { id: 0 ,name: &#39;顶级节点&#39;, children: [] }; data.children = this.handleTree(response.data, &quot;id&quot;, &quot;parentId&quot;); this.mdmMaterialTypeOptions.push(data); }); }, // 取消按钮 cancel() { this.open = false; this.reset(); }, // 表单重置 reset() { this.form = { id: null, number: null, name: null, parentId: null, status: null, createBy: null, createTime: null, updateBy: null, updateTime: null, icon: null, namingrule: null }; this.resetForm(&quot;form&quot;); }, /** 搜索按钮操作 */ handleQuery() { this.getList(); }, /** 重置按钮操作 */ resetQuery() { this.resetForm(&quot;queryForm&quot;); this.handleQuery(); }, /** 新增按钮操作 */ handleAdd(row) { this.reset(); this.getTreeselect(); if (row != null &amp;&amp; row.id) { this.form.parentId = row.id; } else { this.form.parentId = 0; } this.open = true; this.title = &quot;添加物料类型&quot;; }, /** 展开/折叠操作 */ toggleExpandAll() { this.refreshTable = false; this.isExpandAll = !this.isExpandAll; this.$nextTick(() =&gt; { this.refreshTable = true; }); }, /** 修改按钮操作 */ handleUpdate(row) { this.reset(); this.getTreeselect(); if (row != null) { this.form.parentId = row.parentId; } getMdmMaterialType(row.id).then(response =&gt; { this.form = response.data; this.open = true; this.title = &quot;修改物料类型&quot;; }); }, /** 提交按钮 */ submitForm() { this.$refs[&quot;form&quot;].validate(valid =&gt; { if (valid) { if (this.form.id != null) { updateMdmMaterialType(this.form).then(response =&gt; { this.$modal.msgSuccess(&quot;修改成功&quot;); this.open = false; this.getList(); }); } else { addMdmMaterialType(this.form).then(response =&gt; { this.$modal.msgSuccess(&quot;新增成功&quot;); this.open = false; this.getList(); }); } } }); }, /** 删除按钮操作 */ handleDelete(row) { this.$modal.confirm(&#39;是否确认删除物料类型编号为&quot;&#39; + row.id + &#39;&quot;的数据项?&#39;).then(function() { return delMdmMaterialType(row.id); }).then(() =&gt; { this.getList(); this.$modal.msgSuccess(&quot;删除成功&quot;); }).catch(() =&gt; {}); }, /** 导出按钮操作 */ handleExport() { this.download(&#39;mdm/mdmMaterialType/export&#39;, { ...this.queryParams }, `material_type_${new Date().getTime()}.xlsx`) }, /** 导入按钮操作 */ handleImport() { this.upload.title = &quot;导入物料类型&quot;; this.upload.open = true; }, /** 下载模板操作 */ importTemplate() { this.download(&#39;mdm/mdmMaterialType/importTemplate&#39;, { }, `materialtype_template_${new Date().getTime()}.xlsx`) }, // 文件上传中处理 handleFileUploadProgress(event, file, fileList) { this.upload.isUploading = true; }, // 文件上传成功处理 handleFileSuccess(response, file, fileList) { this.upload.open = false; this.upload.isUploading = false; this.$refs.upload.clearFiles(); this.$alert(&quot;&lt;div style=&#39;overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;&#39;&gt;&quot; + response.msg + &quot;&lt;/div&gt;&quot;, &quot;导入结果&quot;, { dangerouslyUseHTMLString: true }); this.getList(); }, // 提交上传文件 submitFileForm() { this.$refs.upload.submit(); } } }; &lt;/script&gt; 上面学习的语法 和代码格式 ,把这块点从迁移vue2 到 vue3
最新发布
07-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值