【Vue】基於UI庫二次組件封裝——ant design table(包括支持slot插槽)


vue現在使用非常廣泛,對於一些公用的功能我們通常也會封裝成組件,同時還有各類的UI組件庫給我們開發提供了便利。

為什么要封裝成組件

  • 能夠把頁面抽象成多個相對獨立的模塊
  • 實現代碼重用,提高開發效率和代碼質量,使得代碼易於維護

為什么要講基於第三方UI庫封裝組件

這段時間經手了幾個項目,都是后台管理系統的,大家知道后台管理系統最多的就是table以及表單,幾乎90%的頁面都會包含這兩個,但從中發現了好幾個問題:

第一,有些項目表格基本沒有做封裝,直接是使用的element-ui或者iview等UI庫提供現成的copy過來的,然后很多頁面可以看到的就是表格、表單的各種邏輯,而且每個頁面基本代碼都相似,不同的就是調用的接口,表單的配置。

第二,雖然有些項目對表格或者表單進行了二次封裝,但是維護起來卻很不方便,參數都是通過一個一個傳遞過來,代碼量大,並且slot也不支持,大大降低了靈活性。

下面以antd-vue封裝一個Table組件為例進行一個簡單的封裝實例。

封裝前考慮的問題?

  • 如何將自己定義的組件 可以支持庫中當前組件所有接收參數和事件。

    如果通過參數一個個傳 第一個參數太多,第二個 如果第三方庫有更新增加了接受參數,自己庫也需要進行更新。
  • 如何將所有傳過來的值 掛載到UI庫的組件上。
  • 如何支持插槽。

如果能解決以上的三個問題,其實也就完成50%了,剩下的就是處理一些邏輯。

我們先來解決第一個問題。

一、如何將自己定義的組件 可以支持庫中當前組件所有接收參數和事件。

下面是antd官方的一個實例:

<template>
  <a-table :columns="columns" :data-source="data">
    <a slot="name" slot-scope="text">{{ text }}</a>
  </a-table>
</template>
<script>
const columns = [
  {
    title: 'Name',
    dataIndex: 'name',
    key: 'name',
    scopedSlots: { customRender: 'name' },
  },
  {
    title: 'Age',
    dataIndex: 'age',
    key: 'age',
    width: 80,
  },
];

const data = [
  {
    key: '1',
    name: 'John Brown',
    age: 32,
    address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
    tags: ['nice', 'developer'],
  },
  {
    key: '2',
    name: 'Jim Green',
    age: 42,
    address: 'London No. 2 Lake Park, London No. 2 Lake Park',
    tags: ['loser'],
  },
];

export default {
  data() {
    return {
      data,
      columns,
    };
  },
};
</script>

現在我要改成可以如下方式使用並且效果一樣,tablePanel是我需要封裝的組件。

<template>
  <TablePanel :columns="columns" :data-source="data">
    <a slot="name" slot-scope="text">{{ text }}</a>
  </TablePanel>
</template>
<script>
const columns = [
  // ...此處省略 同上
];

const data = [
  // ...此處省略 同上
];

export default {
  data() {
    return {
      data,
      columns,
    };
  },
};
</script>

現在上方代碼只傳入了兩個參數,官方文檔是有15+個API參數可以配置的,如果我們一個個傳進去,然后又通過props一個個接口這樣特別繁瑣,而且當UI庫進行更新增加了參數時,組件又需要同步修改。

其實每個組件都有一個props對象,我們只要把子組件的props賦給當前組件的props就可以繼承子組件的所有屬性了。

TablePanel組件:

<template>
    <a-table v-bind="$props" v-on="$listeners"/>//v-bind="$props"支持ant-design所有屬性;v-on="$listeners"支持ant-design所有事件
</template>

<script>
import {Table} from 'ant-design-vue'

export default {
 props: {
    ...Table.props,
    ...myProps
  }     
}
</script>
原文處理第二個和第三個問題的方法沒有看懂,大家能看懂的告訴我一下哦,這里找到另一個方法解決第三個問題的:

父組件:

         <body-table pageMethod="applyPage" :columns="columns">
            <span slot="status" slot-scope="row">
                <a-icon v-show='row.status!=="0"' style="color:#bfbfbf" type="pause-circle" />
                <a-icon v-show='row.status=="0"' class="ant-tag-green" type="check-circle" />
            </span>
            <span slot="type" slot-scope="scope">
                <a-tag :color="row.type === 'private' ? 'orange' : 'green'">
                    {{ scope.record.type.toUpperCase() }}
                </a-tag>
            </span> 
        </body-table>

子組件:

            <a-table 
            size="small" bordered 
            @change="handleTableChange"
            :row-key="record => record.id" 
            :data-source="data" 
            :pagination="pagination"
            :rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange,columnWidth:39}" 
            :rowClassName="(record, index) => (index % 2 === 0 ? 'unOdd' : 'odd')"
            :scroll="{x: 1200, y: this.tableheight}"
            :columns="columns" 
            :loading="loading"  
            >
                <template  v-for="column in columns"  :slot="column.scopedSlots?column.scopedSlots.customRender:''" slot-scope="text,record" >
                    <slot :name="column.scopedSlots?column.scopedSlots.customRender:''" v-bind:scope="record" ></slot>//綁定的scope可以在父組件中使用
                </template>
            </a-table>

參考:https://www.zhihu.com/question/339501753

參考:https://segmentfault.com/a/1190000038483387

v-on="$listeners"的用法詳情見:https://www.cnblogs.com/vickylinj/p/13376391.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM