Vue Render自定义tabled单元格内容

解决问题

只举一个例子(我正好需要用到的)

在写中后台时, 如果对 表格组件 再度封装了, 比如这样的

以element-ui 为例:

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

对html数据化, 封装成一个组件.

// complex-table.vue
<template>
  <el-table
      :data="list"
      style="width: 100%;"
    >
      <el-table-column v-for="col in columns" :key="col.prop" v-bind="col"></el-table-column>
  </el-table>
</template>
<script>
    export default {
    props: {
        columns: Array
    }
  }
</script>

--------------------------
// index.vue
<template>
  <div class="box_container">
    <complex-table     
      :columns="tableColumns"
    />    
  </div>
</template>
<script>
  export default {
    data() {
        return {
        tableColumns: [
          { label: '日期', prop: 'sn', align: 'center' },
          { label: '姓名', prop: 'phone', align: 'center' },
          { label: '地址', prop: 'address', align: 'center' }
        ]
      }
    }
  }
</script>

那么问题来了, 如果我要在table中加入头像列, 但是后端返回的是url地址, 你又怎么办呢,你可以这样

// complex-table.vue
...
  <el-table>
    <el-table-column v-for="col in columns" :key="col.prop" v-bind="col">
      <template slot-scope="scope">
        <template v-if="col.prop==='avatar'">
            <el-avatar :src="row.avatar" />
        </template>
                <template v-else>
          <span>{{ scope.row[col.prop] }}</span>
                </template>
            </template>
    </el-table-column>
  </el-table>
...

// index.vue
...
data() {
  return {
    tableColumns: [
            { label: '头像', prop: 'avatar', align: 'center' },
      { label: '日期', prop: 'date', align: 'center' },
      { label: '姓名', prop: 'name', align: 'center' },
      { label: '地址', prop: 'address', align: 'center' }
    ]
  }
}
...

万一又是 <el-tag> 标签, el-button 不能一直v-if吧

或许也可以使用 ​<component :is="**" v-bind="**" >​这种形式, 如果遇到方法传值又感觉差点什么,差scope传值了

解决方案

​使用函数式组件, 可灵活使用, 原理跟 valueFormat 类似, 不废话直接上代码

新建文件​​​ columnRender.js​

/*
 * @Description: 函数式组件渲染单元表格
 * @Author: 仲灏<izhaong 164165005@qq.com>
 * @Date: 2020-09-16 15:33:25
 * @LastEditors: 仲灏<izhaong 164165005@qq.com>
 * @LastEditTime: 2020-09-16 15:47:23
 */
export default {
  functional: true,
  props: {
    row: Object,
    render: Function
  },
  render(h, ctx) {
    const params = {
      row: ctx.props.row
    }

    return ctx.props.render(h, params)
  }
}
// complexTable
...
<template v-else-if="'render' in col">
  <!-- <component :is="col.tag" v-bind="col.attrs">{{ col.tagValue }}</component> -->
  <Render :row="row" :render="col.render" />
</template>
...


// index.js
tableColumns: [
    { label: 'name', prop: 'name', align: 'center' },
    { label: '是否有效', prop: 'isValid', align: 'center', render: (h, { row }) => {
      return h('el-tag', { attrs: { type: row.isValid ? 'success' : 'info' }}, row.isValid ? '有效' : '无效')
    } }
]

结语

第一次bb这个多话, 之前直接就啪~ 贴代码了.

当然如果封装的组件足够强大, 能够兼顾涵盖该项目大部分业务, 就可以把组件当做页面使用, 全部使用纯数据驱动, 当然你的业务相似度要高

posted @ 2020-09-18 18:24  仲灏  阅读(410)  评论(0编辑  收藏  举报