1. 程式人生 > 實用技巧 >Vue Render自定義tabled單元格內容

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 [email protected]>
 * @Date: 2020-09-16 15:33:25
 * @LastEditors: 仲灝<izhaong [email protected]>
 * @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這個多話, 之前直接就啪~ 貼程式碼了.

當然如果封裝的元件足夠強大, 能夠兼顧涵蓋該專案大部分業務, 就可以把元件當做頁面使用, 全部使用純資料驅動, 當然你的業務相似度要高