使用JSX封装ElementUI Table组件

1,625 阅读1分钟

前言

在日常的开发中我们经常会在table中使用各种表单元素 比如:

  •     1. 为了验证状态 加入  [switch](https://element.eleme.cn/#/zh-CN/component/switch#) 
        2. 为了加入操作行加入 [按钮](https://element.eleme.cn/#/zh-CN/component/button#) 
        3. 为了显示详情加入  [Tooltip 文字提示](https://element.eleme.cn/#/zh-CN/component/tooltip#)
    

这都是很常见的需求,可不是项目经理给你整活,请善待项目经理 除非忍不住

当然为了实现上述的这些操作可以通过在Table中加入插槽来实现。

但是没加一个类型你就要多上一个插槽么?那Vue的组件化理念不是白提了,而且不利于封装 (写那么多插槽不累么,还费事

就在我苦恼怎么去最大程度上封装这些组件的时候,我发现公司提供的组件库,大多数组件都提供了**render函数**

在我想在组件中添加一些没有预设插槽的子组时,我可以很方便的通过render 动态渲染进去,爽到飞起。

正文

这是我实验性封装Table的代码 1.父组件

<template>
  <div class="hello">
        <my-table :tableData='tableData' :tableColumns="tableColumns">
        </my-table>
  </div>
  
</template>

<script>
import  Vue  from 'vue'
import myTable from './myTable/myTableRender.vue'
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  components:{
      myTable
  },
  data(){
      return {
           tableData:[
               {name:'张三',age:14}
               ],
          tableColumns:[
              {
                  label:'姓名',
                  prop:'name'
              },
              {
                  label:'年龄',
                  prop:'age',
                  render(h,data){
                      return (
                          <el-input v-model={data.row.age} placeholder="请输入内容"></el-input>
                      )  
                  }
              }
          ]
      }
  }
}
</script>



2.封装的Table

  <template>
    <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        v-for="(th,key) in tableColumns"
        :key="key"
        :prop="th.prop"
        :label="th.label"
        >
           
            <template slot-scope="scope">
                <ex-slot 
                    v-if='th.render'
                    :render='th.render'
                    :row='scope.row'
                    :column='th'
                    :index='scope.$index'
               />
                 <!-- 这里可以通过判断 插入一些预设的常用组件 比如数字框、下拉框、按钮等等 -->
                <span v-else>{{scope.row[th.prop]}}</span>
              
            </template>

      </el-table-column>
      
    </el-table>
  </template>

  <script>

//////定义一个中间组件////////
/**目的是封装render函数  提供一个空的可以渲染的环境 */

const exSlot={
    functional:true,
    // props都是一些需要传入的值 当然你也可以选择性的传入一些值  这都是为了render函数可以响应式的调用值
    props:{
        index:Number,
        row:Object,
        columns:Object,
        render:Function
    },
    render:(h,data)=>{
    // 这里将值封装起来 以便于我们在父组件里调用
        const params={
            index:data.props.index,
            row:data.props.row
        }
        // columens 代表我们封装的列属性
        // row 代表我们真实传入的这一行的数据
        if(data.props.columns){
            params.columns=data.props.columns
        }
        return data.props.render(h,params)
    }
    
}
/////////////////////

    export default {


      data() {
        return {}
      },
      components:{
          exSlot
      },

      props:{
          tableData:{
              type: Array,
                default: function () {
                    return [];
                },
          },
          tableColumns:{
              type: Array,
                default: function () {
                    return [];
                },
          }
      }
    }

  </script>