Element Table 业务封装与思考

简介: 新项目 Elemnet UI 组件业务封装,封装需求满足后期不修改业务代码,直接更新前端的封装组件的UI库代码即可实现无缝切换UI库的需求。目前新项目的功能产品还在梳理,项目第一期还未开始,前端技术小组先行进行的组件封装。


ab6e014e5be115455412da454949b02a.jpg


前言


新项目 Elemnet UI 组件业务封装,封装需求满足后期不修改业务代码,直接更新前端的封装组件的UI库代码即可实现无缝切换UI库的需求。目前新项目的功能产品还在梳理,项目第一期还未开始,前端技术小组先行进行的组件封装。


Table 组件封装目标


  • 封装的用法要和 Element UI Table 组件的用法保持一致
  • 目的是降低引用(使用)成本
  • 支持纯数据绑定
  • 支持自定义模板满足业务定制化需求


Table 组件封装内容


目录结构


components  封装组件目录
  talbe
    Index.vue
    TableColumn.vue
Views
  CenterPage.vue 组件调用层

table/Index.vue


这个文件默认封装了 el-table 组件外层,里面使用 v-bind="$attrs":xxx="config.xxx" 模式,在 el-table 内层使用 slot 来接受,这样可以满足表格的自定义模板需求,如果只是渲染基本数据,可以直接把el-table-column 也封装好,如代码中的注释部分


<template>
  <div>
      <!-- v-model="config.value" -->
    <el-table
      v-bind="$attrs"
      :height="config.height"
      :max-height="config.maxHeight"
      :stripe="config.stripe"
      :border="config.border"
      :size="config.size"
      :fit="config.fit"
      :show-header="config.showHeader"
      :highlight-current-row="config.highlightCurrentRow"
      :row-class-name="config.rowClassName"
      :row-style="config.rowStyle"
      :cell-class-name="config.cellClassName"
      :cell-style="config.cellStyle"
      :header-row-class-name="config.headerRowClassName"
      :header-row-style="config.headerRowStyle"
      :header-cell-class-name="config.headerCellClassName"
      :header-cell-style="config.headerCellStyle"
      :row-key="config.rowKey"
      :empty-text="config.emptyText"
      :default-expand-all="config.defaultExpandAll"
      :expand-row-keys="config.expandRowKeys"
      :default-sort="config.defaultSort"
      :tooltip-effect="config.tooltipEffect"
      :show-summary="config.showSummary"
      :sum-text="config.sumText"
      :summary-method="config.summaryMethod"
      :span-method="config.spanMethod"
      :select-on-indeterminate="config.selectOnIndeterminate"
      :indent="config.indent"
      :lazy="config.lazy"
      :load="config.load"
      :tree-props="config.treeProps"
      v-on="$listeners"
    >
      <slot></slot>
      <!-- <template v-for="(v, i) in config.columns" >
        <el-table-column v-if="!v.slot" :key="i" :prop="v.prop" :label="v.label" :width="v.width">
        </el-table-column>
        <el-table-column v-else :key="i" :prop="v.prop" :label="v.label" :width="v.width">
          <slot></slot>
        </el-table-column>
      </template> -->
    </el-table>
  </div>
</template>
<script>
export default {
  name: 'Table',
  props: {
    content: {
      type: String,
      default: ''
    },
    config: {
      type: Object,
      default: () => { }
    }
  }
}
</script>

table/TableColumn.vue


这个文件封装的 el-table-column , 这里面同样了用了 slot 主要用于支持表格列中的自定义部分,添加了一个自定义的参数 isNativeRenter ,表示当前列配置是否是原生数据绑定渲染


<template>
  <!-- v-model="config.value" -->
  <el-table-column
    v-bind="$attrs"
    :type="config.type"
    :index="config.index"
    :column-key="config.columnKey"
    :label="config.label"
    :prop="config.prop"
    :width="config.width"
    :min-width="config.minWidth"
    :fixed="config.fixed"
    :render-header="config.renderHeader"
    :sortable="config.sortable"
    :sort-method="config.sortMethod"
    :sort-by="config.sortBy"
    :sort-orders="config.sortOrders"
    :resizable="config.resizeable"
    :formatter="config.formatter"
    :show-overflow-tooltip="config.showOverflowTooltip"
    :align="config.align"
    :header-align="config.headerAlign"
    :class-name="config.className"
    :label-class-name="config.labelClassName"
    :selectable="config.selectable"
    :reserve-selection="config.reserveSelection"
    :filters="config.filters"
    :filter-placement="config.filterPlacement"
    :filter-multiple="config.filterMultiple"
    :filter-method="config.filterMethod"
    :filtered-value="config.filteredValue"
    v-on="$listeners"
  >
    <template slot-scope="{ row, column, $index }">
      <slot :nativeData="[row, column, $index]" name="custom"></slot>
      <span v-if="!config.isNativeRenter">{{ row[column.property] }}</span>
    </template>
    <template slot="header">
      <slot name="header"></slot>
    </template>
  </el-table-column>
</template>
<script>
export default {
  name: 'TableColumn',
  props: {
    content: {
      type: String,
      default: ''
    },
    config: {
      type: Object,
      default: () => { }
    }
  }
}
</script>


注意


这里面的 <template><el-table-column> 的层级结构中间不能有任何其他元素,否则会影响表格列数据的正常排序。如下代码就不可取


<template>
  <div>
    <el-table-column></el-table-column>
  </div>
</template>

CenterPage.vue


基础表格调用,只渲染数据


template

<table :config="table.config" :data="table.data">
  <table-column :config="table.config.columns[0]"></table-column>
  <table-column :config="table.config.columns[1]"></table-column>
  <table-column :config="table.config.columns[2]"></table-column>
</table>


script

table: {
    config: {
      columns: [
        {
          prop: 'date',
          label: '日期'
        },
        {
          prop: 'name',
          label: '姓名'
        },
        {
          prop: 'address',
          label: '地址'
          width: 300
        }
      ]
    },
    data: [{
      date: '2016-05-02',
      name: '王小虎',
      address: '上海市普陀区金沙江路 1518 弄'
    }, {
      date: '2016-05-04',
      name: '王小虎',
      address: '上海市普陀区金沙江路 1517 弄'
    }, {
      date: '2016-05-01',
      name: '王小虎',
      address: '上海市普陀区金沙江路 1519 弄'
    }, {
      date: '2016-05-03',
      name: '王小虎',
      address: '上海市普陀区金沙江路 1516 弄'
    }]
    },


自定义列模板表格

<c-table :config="table3.config" :data="table2.data">
  <table-column :config="table3.config.columns[0]">
    <template slot="custom" slot-scope="{ nativeData }">
      <span style="margin-left: 10px">{{ nativeData[2] }}</span>
    </template>
  </table-column>
  <table-column :config="table3.config.columns[1]">
    <template slot="custom" slot-scope="{ nativeData }">
      <i class="el-icon-time"></i>
      <span style="margin-left: 10px">{{ nativeData[0].date }}</span>
    </template>
  </table-column>
  <table-column :config="table3.config.columns[2]"></table-column>
  <table-column :config="table3.config.columns[3]"> </table-column>
  <table-column :config="table3.config.columns[4]">
    <template slot="custom" slot-scope="{ nativeData }">
      <el-button
        @click="handleSelectClick(nativeData)"
        type="primary"
        size="small"
        >查看</el-button
      >
      <el-button type="danger" size="small">删除</el-button>
    </template>
  </table-column>
</c-table>


数据层

table3: {
  config: {
    columns: [
      {
        width: '50',
        type: 'index'
      },
      {
        prop: 'date',
        label: '日期',
        width: '200',
        key: 'date',
        sortable: true,
        isNativeRenter: true
      },
      {
        prop: 'name',
        label: '姓名',
        key: 'name',
        sortable: true
      },
      {
        prop: 'address',
        label: '地址',
        width: '400',
        key: 'address'
      },
      {
        label: '操作',
        width: '200',
        fixed: 'right',
      }
    ],
    border: true,
    stripe: true,
    size: 'mini'
  },
  data: [{
    date: '2016-05-02',
    name: '王小虎',
    address: '上海市普陀区金沙江路 1518 弄'
  }, {
    date: '2016-05-04',
    name: '王小虎',
    address: '上海市普陀区金沙江路 1517 弄'
  }, {
    date: '2016-05-01',
    name: '王小虎',
    address: '上海市普陀区金沙江路 1519 弄'
  }, {
    date: '2016-05-03',
    name: '王小虎',
    address: '上海市普陀区金沙江路 1516 弄'
  }]
}


封装过程中遇到的问题和思考


  1. 整个封装过程使用到的技术点相关内容,主要为 slot 的合理使用父子组件的互相传值父子组件的事件触发
  2. 组件封装的内容在我们目前项目的高业务复杂度(包含高度自定义设计出来的功能,以及UI层的特殊需求效果)的项目中,当前业务未开展的情况下,无产品原型,无UI设计规范及效果,纯技术层封装对于业务的支持目前不确定,部分组件在开发过程使用可能需要二次调整和修改。
  3. 目前前端封装小组已经封装了一多半的 ElementUI 组件,一些组件在封装中发现,部分封装出来的组件在后期更换UI库时不时很灵活,在不调整业务代码的情况下,支持不同的UI库组件切换封装层的代码需要支持两种情况,或基于新的UI库组件用法修改调用参数进行匹配处理,这部分的后期在更新UI库时组件的修改代价还是很高的。


GitHub 源码地址


https://github.com/gywgithub/element2-package


GitHub 仓库预览地址


https://gywgithub.github.io/element2-package




目录
相关文章
|
1月前
|
设计模式
在实际开发中,什么时候应该使用 `new` 关键字,什么时候应该使用 `Object.create()` 方法?
【10月更文挑战第29天】`new` 关键字适用于创建具有特定类型和初始化逻辑的对象实例,以及实现基于原型链的继承;而 `Object.create()` 方法则适用于基于现有对象创建相似对象、避免构造函数的副作用、创建具有特定原型链的对象等场景。在实际开发中,需要根据具体的需求和设计模式来选择合适的方法来创建对象,以实现更高效、更灵活的代码结构。
|
3月前
Element table组件封装 核心:父子组件传值、传方法
本文介绍了如何基于Element UI的table组件进行二次封装,创建一个具有父子组件传值和传方法功能的自定义表格组件,并提供了封装后的组件如何引入、注册和使用的方法。
144 0
Element table组件封装 核心:父子组件传值、传方法
|
4月前
|
JavaScript 前端开发 Shell
Element-ui Table表格导出功能的实现
Element-ui Table表格导出功能的实现
73 0
ELEMENT组件库,如何让select出现默认值
ELEMENT组件库,如何让select出现默认值
|
7月前
element plus 表各组件怎样和分页组件配合使用
element plus 表各组件怎样和分页组件配合使用
108 0
|
JavaScript
VUE element-ui之table表格全局排序、调用后端接口排序功能
VUE element-ui之table表格全局排序、调用后端接口排序功能
1496 0
element踩坑记录之 element table 获取所点击行数据
element踩坑记录之 element table 获取所点击行数据
让el-table更好用,通过配置的方式
让el-table更好用,通过配置的方式
443 0