286

优雅的使用 element-ui 中的 table 组件

 6 years ago
source link: https://juejin.im/post/5a100d09f265da4324800807
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

优雅的使用 element-ui 中的 table 组件

2017年11月20日 05:51 ·  阅读 56526

经常使用 element-ui 的小伙伴应该对 el-table 组件非常熟悉,通常它长下面这个样子:

<template>
  <el-table :data="tableData">
    <el-table-column
      prop="date"
      label="日期">
    </el-table-column>
    <el-table-column
      prop="name"
      label="姓名">
    </el-table-column>
    <el-table-column
      prop="address"
      label="地址">
    </el-table-column>
  </el-table>
</template>

<script>
export default {
  data () {
    return {
      tableData: [{
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄'
      }, {
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 弄'
      }]
    }
  }
}
</script>复制代码

上面代码非常正确,但总觉的少了点什么?

没错,模版中 el-table-column 几乎一致,重复写了

使用 v-for 来优化模版中的 el-table-column

下面是采用 v-for 的版本,将每一列作为一个配置项传入:

<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: '日期' },
      { prop: 'name', label: '姓名' },
      { prop: 'address', label: '地址' }
    ]
    return {
      tableData: [{
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄'
      }, {
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 弄'
      }]
    }
  }
}
</script>复制代码

这样做的好处在于,如果想再增加一列,完全可以不用动 template,只需要简单的在 this.colConfigs 这个数组中增加一个配置项 { prop: 'xxx', label: 'xxx' } 即可

虽然这样加个配置非常简单,扩展性也比之前直接写模版好,但是如果我有一列是要渲染几个按钮,上面的方式就不起作用了

换句话说,我们即想要简单的属性可以直接加个配置项渲染出来,又希望复杂的渲染能在模版中写出来,要怎么实现呢?

巧用 slot,为 el-table 封装一层

我们先来看一下封装的组件 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>复制代码

这个封装实际上就是把前面的 colConfigs 作为一个 prop 传入,但是跟上面例子有一点不同的是,配置项中多了一个 slot 属性,通过这个属性,我们就可以像文章最开始那样在模版中写了,用法如下:

<template>
  <my-table
    :data="tableData"
    :col-configs="colConfigs">
    <!-- slot="opt" 不能省略,需要与下面配置项中的对应 -->
    <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: '日期' },
      { prop: 'name', label: '姓名' },
      { prop: 'address', label: '地址' },
      // 模版中的元素需要对应的有 slot="opt" 属性
      { slot: 'opt' }
    ]
    return {
      tableData: [{
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄'
      }, {
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 弄'
      }]
    }
  }
}
</script>复制代码

现在我们想要增加一个列,只要加个配置项,或者加个 slot ,完美~

等等,假设我的 table 中有几列渲染比较复杂,那几列又都比较相似,像下面这种:

<template>
  <my-table
    :data="tableData"
    :col-configs="colConfigs">
    <el-table-column label="变化" slot="change">
      <span :slot-scope="row">
        {{ row['change'] > 0 ? '+' + row['change']: row['change'] }}
      </span>
    </el-table-column>
    <el-table-column label="趋势" slot="trend">
      <span :slot-scope="row">
        {{ row['trend'] > 0 ? '+' + row['trend']: row['trend'] }}
      </span>
    </el-table-column>
  </my-table>
</template>复制代码

又重复写模版了...

使用 :is="component"

我们可以为配置项再增加一个属性 component, 用户可以指定 component 属性来特殊处理某列,实现如下:

// 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>复制代码

然后上面的例子就可以改写成:

<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: '变化' component: PrefixPlusText },
      { prop: 'name', label: '趋势', component: PrefixPlusText },
    ]
    return {
      tableData: [{
        change: '12%',
        trend: '10%
      }, {
        change: '-12%',
        trend: '-10%'
      }]
    }
  }
}
</script>复制代码

table 作为数据展示组件,在日常开发中经常被用到,通过这篇文章,可以看到结合 vueslot/component 特性,做一层封装,可以大大简化 table 的使用,大部分时候只需写一个配置属性就可以了。

最后给一个小 demo


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK