element-ui table組件如何使用 render屬性

前言

原由:
在使用 element-ui table組件時,因爲表列比較多一個個寫特別麻煩,因此想經過將全部表頭定義成一個數組,經過遍歷多方式去實現。這樣解決了手寫不少 el-table-column 的狀況。
障礙:
相似於下面自定義表列的樣式,它是經過 slot-scope 去覆蓋 el-table-column 內部slot的樣式實現的。那咱們在遍歷表頭數組的時候如何實現呢? html

參考:
用過 react 開發會常常用到 ant design ,其中它的 table 組件是能夠接受 render屬性的,下面使用table組件時,只須要定義好,columns(表頭列) data(表的具體數據)便可。總體看起來很簡潔 去渲染自定義的組件的。 點擊查看 antdesign

demo:
codepen demo地址react

const columns = [
  {
    title: 'Name',
    dataIndex: 'name',
    render: (text, row, index) => {
      if (index < 4) {
        return <a>{text}</a>;
      }
      return {
        children: <a>{text}</a>,
        props: {
          colSpan: 5,
        },
      };
    },
  }]
 const const data = [
  {
    key: '1',
    name: 'John Brown',
    age: 32,
    tel: '0571-22098909',
    phone: 18889898989,
    address: 'New York No. 1 Lake Park',
  }]
ReactDOM.render(<Table columns={columns} dataSource={data} bordered />, mountNode);
複製代碼

在 Vue 中實現 render 屬性

接下來咱們要實現下圖的table的樣式,可是這一次咱們採用 render 傳參數的方式element-ui

思路

  1. 父組件將須要渲染的列表經過 props 傳遞給子組件
  2. 子組件使用 slot 並填充默認渲染的 el-table-column 方式爲 prop 渲染 data 中傳遞的值
  3. 子組件經過 slot 將值傳回給父組件,父組件經過 slot-scope 接受到子組件的值,判斷該項是否有 render 屬性,有的話在組件標籤添加 render 屬性返回的 html 去覆蓋 slot 中默認的值。

子組件定義默認值

有了上面的思路,去實現子組件。咱們須要知道一點,每一個 el-table-column 只是定義了一列的表頭和數據,而 :data="tableList" 中的每項值是定義了一行的數據。因此 el-table-column 是按列來分,data 是按行來分數組

  1. 經過props 去接受表頭列表,數據列表
  2. 遍歷表頭數據,而且將 el-table-column 做爲默認數據,使用 slot 包裹起來
  3. 經過 slot 想父組件傳遞當前項的數據
<template>
    <el-table :data="tableList" style="width:500px">
      <template v-for="item in propList">
        <slot :content="item">
          <el-table-column :key="item.id" :prop="item.prop" :label="item.label"></el-table-column>
        </slot>
      </template>
    </el-table>
</template>
<script>
    export default {
        props:{
          propList:{
            type:Array,
            default:()=>[]
          },
          tableList:{
            type:Array,
            default:()=>[]
          },
        }
    }
</script>
複製代碼

父組件定義

父組件經過 slot-scope 來接受到子組件傳遞過來的數據,而後判斷是否有 render 屬性來肯定是否用要去自定義樣式覆蓋默認的 slotbash

  1. 首先看傳遞給子組件的表頭數據,能夠看到,第二,三行列表中有一個render屬性,它是一個函數並返回一個 html 的字符串。babel

  2. tableList就是普通的數據,也就是數據的 key 值去渲染對應的數據antd

  3. 圖片這列舉例子,當父組件經過 props 將 {label,prop,id,render} 傳遞給子組件後,子組件有經過 slot 將值傳遞迴父組件。antdesign

    • 到這裏有些人會有疑問,爲何要將數據這樣傳來傳去,由於咱們在子組件中定義好了默認樣式,而父組件中須要判斷該值是否須要自定義樣式,去覆蓋子組件中的樣式。
    • 這些自定義樣式就是一開始,在render函數中返回的 html 字符串
    • 爲啥 React 直接返回 jsx ,而Vue須要返回 html 字符串,由於react自己就是使用 JSX 來渲染模版的,最終都會經過 babel 編譯成 React.createElement ,而Vue是經過 template 來渲染模版的,這裏經過定義 template 模版字符串,最終經過 v-html 來解析
  4. 爲何這裏有兩個 slot-scope ,第一個是 slot-item 的,組件內部經過 slot-scope 將值傳遞出來。而第二個是 el-table-item 的,ui組件內部一樣將數據經過 slot-scope 傳遞傳來。函數

  5. 經過第一個 slot-scope 拿到 propList 中的定義的 render 函數,經過第二個 slot-scope 拿到 table 組件內部傳遞出來的數據,將數據傳遞給 render 函數去生成自定義模版post

  6. 最終經過 v-html 去解析生成的字符串模版

<slot-item :propList="propList" :tableList="tableList">
    <template slot-scope="{content}" v-if="content.render">
        <el-table-column :label="content.label">
            <template slot-scope="{$index,row}">
                <div v-html="content.render(row)"></div>
            </template>
        </el-table-column>
    </template>
</slot-item>
    export default {
        components:{
            SlotItem
        },
        data () {
            return { 
                propList:[
                    {label:'姓名',prop:'name',id:1},
                    {label:'圖片',prop:'pic',id:2,render:({pic})=>{
                        return `<img style="width:30px;height:30px" src='${pic}' />`
                    }},
                    {label:'操做',prop:'operate',id:3,render:({text})=>{
                        return `<div style="color:#999">${text}</div>`
                    }},
                ],
                tableList:[
                    {name:'章三',pic:'https://zh-static-files.oss-cn-hangzhou.aliyuncs.com//karazhan/content/poster/2019/11/16e30c192f6.png',text:'新增'},
                    {name:'里斯',pic:'https://zh-static-files.oss-cn-hangzhou.aliyuncs.com//karazhan/content/poster/2019/11/16e30c2797e.png',text:'刪除'},
                    {name:'網舞',pic:'https://zh-static-files.oss-cn-hangzhou.aliyuncs.com//karazhan/content/poster/2019/11/16e30c33144.png',text:'跳轉'},
                ]
            }
        }
    }
</script>
複製代碼

結尾

有了render屬性,能夠想 ant-design 那樣簡潔的屬性 ui組件模版了!

相關文章
相關標籤/搜索