Those of you who use Element-UI regularly will be familiar with the El-Table component, which usually looks like this:

<template>
  <el-table :data="tableData">
    <el-table-column
      prop="date"
      label="Date">
    </el-table-column>
    <el-table-column
      prop="name"
      label="Name">
    </el-table-column>
    <el-table-column
      prop="address"
      label="Address">
    </el-table-column>
  </el-table>
</template>

<script>
export default {
  data () {
    return {
      tableData: [{
        date: '2016-05-02',
        name: 'Wang Xiaohu',
        address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
      }, {
        date: '2016-05-04',
        name: 'Wang Xiaohu',
        address: Lane 1517, Jinshajiang Road, Putuo District, Shanghai
      }]
    }
  }
}
</script>Copy the code

The above code is very correct, but something is missing?

Yes, the el-table-column in the template is almost identical. It’s repeated

Use V-for to optimize el-table-column in the template

Here is the v-for version, passing each column as a configuration item:

<template>
  <el-table :data="tableData">
    <el-table-column
      v-for="{ prop, label } in colConfigs"
      :key="prop"
      :prop="prop"
      :label="label">
    </el-table-column>
  </el-table>
</template>

<script>
export default {
  data () {
    this.colConfigs = [
      { prop: 'date', label: 'date' },
      { prop: 'name', label: 'name' },
      { prop: 'address', label: 'address'}]return {
      tableData: [{
        date: '2016-05-02',
        name: 'Wang Xiaohu',
        address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
      }, {
        date: '2016-05-04',
        name: 'Wang Xiaohu',
        address: Lane 1517, Jinshajiang Road, Putuo District, Shanghai
      }]
    }
  }
}
</script>Copy the code

The nice thing about this is that if you want to add another column, you can leave the template out of the array and simply add a configuration item {prop: ‘XXX ‘, label:’ XXX ‘} to the array this.colConfigs

Although it’s easy to add a configuration like this and it’s much more scalable than writing the template directly, it doesn’t work if I have a column that renders a few buttons

In other words, we want simple attributes that can be rendered directly with a configuration item, but we also want complex renderings that can be written in a template. How do we do that?

Use slot skillfully to encapsulate a layer for el-Table

Let’s take a look at the encapsulated component my-table:

// my-table.vue
<template>
  <el-table :data="data">
    <template v-for="colConfig in colConfigs">
      <slot v-if="colConfig.slot" :name="colConfig.slot">
      <el-table-column v-bind="colConfig"></el-table-column>
    </template>  
  </el-table>
</template>

<script>
export default {
  props: ['colConfigs'.'data']
}
</script>Copy the code

This wrapper actually passes colConfigs as a prop, but differs a little from the previous example by adding a slot property to the configuration item. With this property, we can use the template as we did at the beginning of this article.

<template>
  <my-table
    :data="tableData"
    :col-configs="colConfigs"> <! -- slot="opt"The value must correspond to the following configuration items: --> <el-table-column slot="opt">
      <el-button size="mini" slot-scope="{ row }"</el-button> </el-table-column> </my-table> </template> <script>export default {
  data () {
    this.colConfigs = [
      { prop: 'date', label: 'date' },
      { prop: 'name', label: 'name' },
      { prop: 'address', label: 'address'}, // Elements in the template need to correspond to slot="opt"Attributes {slot:'opt'}]return {
      tableData: [{
        date: '2016-05-02',
        name: 'Wang Xiaohu',
        address: Lane 1518, Jinshajiang Road, Putuo District, Shanghai
      }, {
        date: '2016-05-04',
        name: 'Wang Xiaohu',
        address: Lane 1517, Jinshajiang Road, Putuo District, Shanghai
      }]
    }
  }
}
</script>Copy the code

Now we want to add a column, just add a configuration item, or add a slot, perfect

Wait, let’s say I have a table with a few columns that are complicated to render, and those columns are all similar, like this:

<template>
  <my-table
    :data="tableData"
    :col-configs="colConfigs">
    <el-table-column label="Change" slot="change">
      <span :slot-scope="row">
        {{ row['change'] > 0?'+' + row['change']: row['change'] }}
      </span>
    </el-table-column>
    <el-table-column label="Trends" slot="trend">
      <span :slot-scope="row">
        {{ row['trend'] > 0?'+' + row['trend']: row['trend'] }}
      </span>
    </el-table-column>
  </my-table>
</template>Copy the code

Writing templates again…

Use: is = “component”

We can add a component attribute to the configuration item. The user can specify the Component attribute to handle a particular column as follows:

// my-table.vue
<template>
  <el-table :data="data">
    <template v-for="colConfig in colConfigs">
      <slot v-if="colConfig.slot" :name="colConfig.slot">
      <component
        v-else-if="colConfig.component"
        :is="config.component" 
        :col-config="colConfig">
      </component>
      <el-table-column v-else v-bind="colConfig"></el-table-column>
    </template>  
  </el-table>
</template>

<script>
export default {
  props: ['colConfigs'.'data']
}
</script>Copy the code

The above example can then be rewritten as:

<template>
  <my-table
    :data="tableData"
    :col-configs="colConfigs">
  </my-table>
</template>
<script>

const PrefixPlusText = {
  props: ['colConfig'],
  template: `
    <el-table-column :label="colConfig.label">
      <span :slot-scope="{ row }">
        {{ parseInt(row[colConfig.prop]) > 0 ? '+' + row[colConfig.prop] : row[colConfig.prop] }}
      </span>
    </el-table-column>
  `
}

export default {
  data () {
    this.colConfigs = [
      { prop: 'change', label: 'change' component: PrefixPlusText },
      { prop: 'name', label: 'trend', component: PrefixPlusText },
    ]
    return {
      tableData: [{
        change: '12%',
        trend: '10% }, { change: '- 12%', trend: '- 10%' }] } } } Copy the code

conclusion

Table as a data presentation component is often used in daily development. In this article, we can see that combining the slot/ Component feature of VUE and a layer of encapsulation can greatly simplify the use of tables. Most of the time, only one configuration property is needed.

And then I’ll give you a little demo