当前位置: 首页 > Web前端 > vue.js

基于ElementUI对Table二次封装,动态生成Column

时间:2023-04-01 01:20:36 vue.js

前端小白,多多指教。个人感觉写Vue比写模板更烦人。比如使用ElementUI的Table组件,有多少列就写多少Column很麻烦。但是使用JS代码可以非常灵活。幸运的是,Vue支持渲染功能,这意味着组件可以用JS代码实现。首先,让我们明确我们的封装目标。对于仅用于展示的通用列,只要指定prop和label,即可自动生成。保留原有Column的槽位能力,用户可以自定义显示列。自定义数据格式化程序。可选择控制是否显示列。使用效果下面我们来看看这个二包组件到底能做什么。简单的数据展示如果是纯数据展示,那么就写然后给它你需要的列和数据就可以了。个人觉得很方便。exportdefault{name:"app",components:{EluiDynTable,},data(){return{tableDesc:[{prop:"name",label:"name"},{prop:"city",标签:"city"},{prop:"born",label:"timeofbirth",formatter:"ts"},],tableData:[{name:"Alice",city:"上海",born:946656000000,},{name:"Bob",city:"Hongkong",出生:946699994000,},],};},};定义列,比如想在最右边添加一个功能操作按钮,可以这样自定义删除

exportdefault{name:"app",components:{EluiDynTable,EluiDynColumn,},data(){返回{tableDesc:[{prop:"name",label:"Name"},{prop:"city",label:"city"},{prop:"born",label:"出生时间",formatter:"ts"},{prop:"operation",label:"操作",fixed:"right"},],tableData:[{name:"Alice",city:"Shanghai",born:946656000000,},{name:"Bob",city:"Hongkong",born:946699994000,},],};},methods:{handleClick(row,index){/*eslint-disableno-console*/console.log(`deleting${row.name}at${index}`);},},};不建议使用调用组件的切换功能。函数签名如下:toggle(prop,hidden);prop用于指定在哪一列。如果不指定隐藏值(boolean),会在显示和不显示之间来回切换,如果指定,则使用指定的值。为此,我们首先需要为各种数据类型准备一些常用的格式化程序。我开箱即用。具体代码在这里:functionformatNumber(prop){}functionformatArray(array,extra){}functionformatTimestamp(ts){}functionformatSecond(second){}functionformatterByType(prop){}exportfunctionformat({formatter,prop,scope,extra}){}如果内置的formatter不能满足要求,也可以自定义,给formatter传custom,然后在extra中指定一个formatter,应该是函数类型,具体函数签名是这样的。extra.formatter(道具,范围);对于项目中会广泛使用的格式化器,可以全局注册,提供API:setFormatter(type,formatter);那么我们就简单封装一下ElColumn,默认会调用defaultslotformatter对数据进行格式化和展示,而headerslot展示的是标签值。注意把原来的插槽再暴露出来,这样使用的时候就可以自定义了。{{formatRow(scope.row[prop],范围)}}最后使用流染函数,实现了一个表组constEluiDynTable={name:"EluiDynTable",props:{data:{type:Array,default:()=>[],},desc:{类型:数组,默认值:()=>[],},},methods:{toggle(prop,hidden){constd=this.desc.find((e)=>e.prop===prop);如果(d){如果(隐藏!==未定义){d.hidden=!!hidden;}else{d.hidden=!d.hidden;}this.$forceUpdate();}},},render:function(h){constisDynColumn=(c)=>c.componentOptions&&c.componentOptions.Ctor.extendOptions.name==="EluiDynColumn";constdynColumns=(this.$slots.default||[]).filter(isDynColumn);constkeyOf=(c)=>c.componentOptions.propsData.prop;constcolumnGroups=group(dynColumns,keyOf);const孩子=[];for(letdofthis.desc){if(d.hidden){继续;}letchild=columnGroups[d.prop];if(child){constpropKeys=Object.keys(child.componentOptions.Ctor.options.props);for(letkind){if(propKeys.indexOf(k)>=0){child.componentOptions.props数据[k]=d[k];}else{child.data.attrs[k]=d[k];}}else{constpropKeys=Object.keys(EluiDynColumn.props);常量道具={};const属性={};for(letkind){if(propKeys.indexOf(k)>=0){props[k]=d[k];}else{属性[k]=d[k];}}child=h(EluiDynColumn,{props,attrs,});}children.push(child);}returnh(Table,{props:this.$props,attrs:this.$attrs},children);},};可以看到的代码细节是,我只会过滤掉default槽中的EluiDynColumn组件,以为是自定义列,然后遍历表描述desc。如果用户有自定义组件,则使用自定义组件,否则会自动生成EluiDynColumn组件,为EluiDynColumn的props和attrs赋值,因为EluiDynColumn会通过v-bind将attrs绑定到ElColumn,从而完美保留原始ElColumn的特征。另一个细节是隐藏属性,用于控制列的显示。render函数最终返回一个ElTable的VNode。完整代码在这里