Writing in the front

Thanks to the front-end team of Ele. me for providing elememt-UI, a componentized framework. Element-ui is used as the basic component of this paper.

The background

In the process of developing some systems, it is inevitable to use table for data display. Let’s start with the EL-Table component.

Very simple to use components, according to the provided data data, configure each column of the table data and label. Sure, this all seems fine, but if you’re developing a lot of pages that contain tables, you’ll find that you need to copy el-table-column every time, or you could say you already attribute the entire element-UI framework document. However, there is a lot of duplicate code and a lot of code. As a programmer, doesn’t it feel a little weird to have to write a piece of code that you’ve already written?

Data driven

<el-table
  :data="tabledata">
   <el-table-column
    v-for="(item,key) in columnsConfig"
    :key="key"
    :label="item.label"
    :prop="item.prop">
    </el-table-column>
</el-table>
Copy the code
data () {
  return {
    columnsConfig: [{
      prop: 'logicCategoryId',
      label: 'ID'
    }, {
      prop: 'name',
      label: 'Category name'}}}]Copy the code

This can easily render the table.

Here’s a little trick

El – table – column transformation

<el-table
  :data="tabledata">
   <el-table-column
    v-for="(item,key) in columnsConfig"
    :key="key"
    v-bind="item"</el-table-column> </el-table-column>Copy the code

V-bind can bind an object, which reads each property of the item object and uses it in the component. For example, if you increase width: 100, you only need to increase width in columnsConfig, and el-table-column does not need to be changed.

What to do with slots

<el-table-column
  label="Date"
  width="120">
  <template scope="scope">{{ scope.row.date }}</template>
</el-table-column>
Copy the code

Obviously, the el-table-column slots configuration is not available in the columnsConfig array. Find a solution in the source code ([email protected]@element-ui\packages\table\ SRC \table-column.js), create hook function code is as follows:

First of all, how do I write columnsConfig

columnsConfig: [{
  cellType: 'slots'// Not all columns need to be overwritten, add a field mark under prop:'logicCategoryId',
  label: 'ID',
  renderCell: (scope) => {
    return (
      <el-button type="text" on-click={() => that.viewGoods(scope.row)}>
        { scope.row.productCount }
      </el-button>
    )
  }
}, {
  prop: 'name',
  label: 'Category name'}].Copy the code

Secondly, develop a new component called Column-plus. vue with the following code

<script>
import { TableColumn } from 'element-ui'// renderCell function, type extensible const renderCell = {slots:function(h, data) {// Accept the renderCell function passed inlet renderCell = () => {
      return this.renderCell ? this.renderCell(data) : ' '
    }
    return <div class="cell">{ renderCell(h, data) }</div>
  }
}
exportDefault {extends: TableColumn,// Extends el-table-column props: {prop: {type: [String, Number]
    },
    cellType: {
      type: String,
      validator: function (value) {
        let valid = ['text'.'input'.'slots'].includes(value) ! Valid && console.error(' columnPlus component is not suitable${value}Type `)return valid
      }
    },
    renderCell: {
      type: Function}}, // el-table-column calls its own columncreated () {
    if (renderCell[this.cellType]) {
      this.columnConfig.renderCell = renderCell[this.cellType].bind(this)
    }
  }
}
</script>

Copy the code

Finally, the component is used to configure the data through the template

<el-table
  :data="tabledata">
   <column-plus v-bind="item" v-for="(item,key) in columnConfigs" :key="key">
  </column-plus>
</el-table>
Copy the code

The configuration data

columnsConfig: [{
  cellType: 'slots',
  prop: 'logicCategoryId',
  label: 'ID',
  renderCell: (scope) => {
    return (
      <el-button type="text" on-click={() => that.viewGoods(scope.row)}>
        { scope.row.productCount }
      </el-button>
    )
  }
}, {
  prop: 'name',
  label: 'Category name'* * * *}]Copy the code

Write in the back

Component development implements configurable development, which can achieve the purpose of rapid development and simplify code. The vue extends and mixins properties are both inherited, property and method overridden, and the hook function is called by its parent class first. In the above example (el-table-column is called by its parent class first), but the difference is:

  • Extends extends a single inheritance with a high priority
  • Mixins have multiple inheritance and low priority

In addition, vue-CLI writing using JSX requires three plug-ins to be installed.

  • babel-helper-vue-jsx-merge-props
  • babel-plugin-syntax-jsx
  • babel-plugin-transform-vue-jsx

supplement

Released a day did not expect to have such a small partner to read, there are a few points need to add.

Iview is the same, later to look at the iView document indeed, has not used iView development, I do not know that the table is also used to render to achieve, indeed after sharing I learned more, thank you @hold.

This is the code for the iView table component

render: (h, params) => {
    return h('div', [
        h('Button', {
            props: {
                type: 'text',
                size: 'small'}},'View'),
        h('Button', {
            props: {
                type: 'text',
                size: 'small'}},'Edit')]); }Copy the code

Of course, after using render, you need to use filter, which is more awkward. However, vue filter is also syntactic sugar, the final compilation is compiled into function processing.

What if you want to use filter?

data () {
    return {
      columns: [{
        renderCell: (scope) => {
          return (
              { that.stateTxt(scope.row.state)}
          )
        }
      }]
    }
    },
    methods: {
        stateTxt (val) {}
    }
Copy the code

If you’ve ever written react, you know how it works.

Therefore, the front-end has always written JS in HTML, or HTML to write JS, are the topic of debate, how to choose their own development.

Not using the Render code looks like this

<template>
    <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="date"
        label="Date"
        width="180">
      </el-table-column>
      <el-table-column
        prop="name"
        label="Name"
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="Address">
      </el-table-column>
    </el-table>
  </template>
Copy the code

Using render processing looks like this

<el-table
  :data="tabledata">
   <column-plus v-bind="item" v-for="(item,key) in columnConfigs" :key="key">
  </column-plus>
</el-table>

data () {
    return {
      columnConfigs: [{
        label: 'date',
        width: '180',
        prop: 'date'
      }, {
        label: 'name',
        width: '180',
        prop: 'name'
      }, {
        label: 'address',
        prop: 'address'}}}]Copy the code