最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

封裝Vue Element的table表格組件的示例詳解

 更新時(shí)間:2020年08月19日 09:53:25   作者:小壞先生  
這篇文章主要介紹了封裝Vue Element的table表格組件的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧

在封裝Vue組件時(shí),我依舊會(huì)交叉使用函數(shù)式組件的方式來實(shí)現(xiàn)。關(guān)于函數(shù)式組件,我們可以把它想像成組件里的一個(gè)函數(shù),入?yún)⑹卿秩旧舷挛?render context),返回值是渲染好的HTML(VNode)。它比較適用于外層組件僅僅是對(duì)內(nèi)層組件的一次邏輯封裝,而渲染的模板結(jié)構(gòu)變化擴(kuò)展不多的情況,且它一定是無狀態(tài)、無實(shí)例的,無狀態(tài)就意味著它沒有created、mounted、updated等Vue的生命周期函數(shù),無實(shí)例就意味著它沒有響應(yīng)式數(shù)據(jù)data和this上下文。

我們先來一個(gè)簡(jiǎn)單的Vue函數(shù)式組件的例子吧,然后照著這個(gè)例子來詳細(xì)介紹一下。

export default {
 functional: true,
 props: {},
 render(createElement, context) {
 return createElement('span', 'hello world')
 }
}

Vue提供了一個(gè)functional開關(guān),設(shè)置為true后,就可以讓組件變?yōu)闊o狀態(tài)、無實(shí)例的函數(shù)式組件。因?yàn)橹皇呛瘮?shù),所以渲染的開銷相對(duì)來說較小。

函數(shù)式組件中的Render函數(shù),提供了兩個(gè)參數(shù)createElement和context,我們先來了解下第一個(gè)參數(shù)createElement。

createElement說白了就是用來創(chuàng)建虛擬DOM節(jié)點(diǎn)VNode的。它接收三個(gè)參數(shù),第一個(gè)參數(shù)可以是DOM節(jié)點(diǎn)字符串,也可以是一個(gè)Vue組件,還可以是一個(gè)返回DOM節(jié)點(diǎn)字符串或Vue組件的函數(shù);第二個(gè)參數(shù)是一個(gè)對(duì)象,這個(gè)參數(shù)是可選的,定義了渲染組件所需的參數(shù);第三個(gè)參數(shù)是子級(jí)虛擬節(jié)點(diǎn),可以是一個(gè)由createElement函數(shù)創(chuàng)建的組件,也可以是一個(gè)普通的字符串如:'hello world',還可以是一個(gè)數(shù)組,當(dāng)然也可以是一個(gè)返回DOM節(jié)點(diǎn)字符串或Vue組件的函數(shù)。

createElement有幾點(diǎn)需要注意:

  • createElement第一個(gè)參數(shù)若是組件,則第三個(gè)參數(shù)可省略,即使寫上去也無效;
  • render函數(shù)在on事件中可監(jiān)聽組件$emit發(fā)出的事件
  • 在2.3.0之前的版本中,如果一個(gè)函數(shù)式組件想要接收prop,則props選項(xiàng)是必須的。在2.3.0或以上的版本中,你可以省略props選項(xiàng),組件上所有的attribute都會(huì)被自動(dòng)隱式解析為prop。

函數(shù)式組件中Render的第二個(gè)參數(shù)是context上下文,data、props、slots、children以及parent都可以通過context來訪問。

在2.5.0及以上版本中,如果你使用了單文件組件,那么基于模板的函數(shù)式組件可以這樣聲明:<template functional></template>, 但是如果Vue組件中的render函數(shù)存在,則Vue構(gòu)造函數(shù)不會(huì)從template選項(xiàng)或通過el選項(xiàng)指定的掛載元素中提取出的HTML模板編譯渲染函數(shù),也就是說一個(gè)組件中templete和render函數(shù)不能共存,如果一個(gè)組件中有了templete,即使有了render函數(shù),render函數(shù)也不會(huì)執(zhí)行,因?yàn)閠emplate選項(xiàng)的優(yōu)先級(jí)比render選項(xiàng)的優(yōu)先級(jí)高。

到這里,Vue函數(shù)式組件介紹的就差不多了,我們就來看看Element的表格組件是如何通過函數(shù)式組件來實(shí)現(xiàn)封裝的吧。

效果圖:

1、所封裝的table組件

<template>
 <el-table :data="config.tableData" style="width: 100%" v-on="cfg.on" v-bind="cfg.attrs">
 <el-table-column v-if="cfg.hasCheckbox" type="selection" width="55" label="xx" />
 <el-table-column v-for="n in cfg.headers" :prop="n.prop" :label="n.name" :key="n.prop" v-bind="{...columnAttrs, ...n.attrs}">
 <template slot-scope="{row}">
 <Cell :config="n" :data="row" />
 </template>
 </el-table-column>
 </el-table>
</template>

<script>
import Cell from './cell'

export default {
 components: {
 Cell,
 },
 props: {
 config: Object,
 },
 data(){
 return {
 columnAttrs: {
 align: 'left',
 resizable: false,
 },
 cfg: {
 on: this.getTableEvents(),
 attrs: {
  border: true,
  stripe: true,
 },
 ...this.config,
 },
 checked: [],
 }
 },
 methods: {
 getTableEvents(){
 let {hasCheckbox = false} = this.config, events = {}, _this = this;
 if(hasCheckbox){
 //綁定事件
 Object.assign(events, {
  'selection-change'(v){
  _this.checked = v;
  },
 });
 }

 return events;
 },
 getChecked(){
 return this.checked;
 },
 },
}
</script>

2、匯總表格每一列的cell.js:

import * as Components from './components';
let empty = '-'
export default {
 props: {
 config: Object,
 data: Object,
 },
 functional: true,
 render: (h, c) => {
 let {props: {config = {}, data = {}}} = c, {prop, type = 'Default'} = config, value = data[prop] || config.value, isEmpty = value === '' || value === undefined;
 return isEmpty ? h(Components.Default, {props: {value: empty}}) : h(Components[type], {props: {value, empty, data, ...config}});
 }
}

3、不同于封裝React AntD的table表格組件時(shí)將表格的每一列的渲染都集中在了一個(gè)table.js中,本次封裝將每一列的渲染單獨(dú)分開成多個(gè)vue組件,最后再合并在一個(gè)components.js文件中一起進(jìn)行匹配。

1)整合文件components.js:

import Date  from './Date';
import Default from './Default';
import Currency from './Currency';
import Enum  from './Enum';
import Action from './Action';
import Link  from './Link';
import Loop  from './Loop';
import Popover from './Popover';

export {
 Default,
 Date,
 Currency,
 Enum,
 Action,
 Link,
 Loop,
 Popover,
}

2)日期列Date.vue

<template functional>
 <span>{{props.value | date(props.format)}}</span>
</template>

3)默認(rèn)列Default.vue

<template functional>
 <span>{{props.value}}</span>
</template>

4)金額千分位列Currency.vue

<template functional>
 <span>{{props.value | currency}}</span>
</template>

5)映射列Enum.js

let mapIdAndKey = list => list.reduce((c, i) => ({...c, [i.key]: i}), {});

let STATUS = {
 order: mapIdAndKey([
 {
  id: 'draft',
  key: 'CREATED',
  val: '未提交',
 },
 {
  id: 'pending',
  key: 'IN_APPROVAL',
  val: '審批中',
 },
 {
  id: 'reject',
  key: 'REJECT',
  val: '審批駁回',
 },
 {
  id: 'refuse',
  key: 'REFUSE',
  val: '審批拒絕',
 },
 {
  id: 'sign',
  key: 'CONTRACT_IN_SIGN',
  val: '合同簽署中',
 },
 {
  id: 'signDone',
  key: 'CONTRACT_SIGNED',
  val: '合同簽署成功',
 },
 {
  id: 'lendDone',
  key: 'LENDED',
  val: '放款成功',
 },
 {
  id: 'lendReject',
  key: 'LOAN_REJECT',
  val: '放款駁回',
 },
 {
  id: 'cancel',
  key: 'CANCEL',
  val: '取消成功',
 },
 {
  id: 'inLend',
  key: 'IN_LOAN',
  val: '放款審批中',
 },
 ]),
 monitor: mapIdAndKey([
 {
  key: '00',
  val: '未監(jiān)控',
 },
 {
  key: '01',
  val: '監(jiān)控中',
 },
 ]),
}

export default {
 functional: true,
 render(h, {props: {value, Enum, empty}, parent}){
 let enums = Object.assign({}, STATUS, parent.$store.getters.dictionary),
  {name = '', getVal = (values, v) => values[v]} = Enum, _value = getVal(enums[name], value);
  
 if( _value === undefined) return h('span', _value === undefined ? empty : _value);

 let {id, val} = _value;
 return h('span', {staticClass: id}, [h('span', val)]);
 }
}

6)操作列Action.js

const getAcitons = (h, value, data) => {
 let result = value.filter(n => {
 let {filter = () => true} = n;
 return filter.call(n, data);
 });

 return result.map(a => h('span', {class: 'btn', on: {click: () => a.click(data)}, key: a.prop}, a.label))
}

export default {
 functional: true,
 render: (h, {props: {value, data}}) => {
 return h('div', {class: 'action'}, getAcitons(h, value, data))
 },
}

7)帶有可跳轉(zhuǎn)鏈接的列Link.vue

<template functional>
 <router-link :to="{ path: props.url, query: {id: props.data.id} }">{{props.value}}</router-link>
</template>

8)可循環(huán)展示數(shù)組數(shù)據(jù)的列Loop.vue

<template functional>
 <div v-html="props.Loop(props.value)" />
</template>

9)當(dāng)內(nèi)容過多需要省略并在鼠標(biāo)移入后彈出一個(gè)提示窗顯示全部?jī)?nèi)容的列Popover.vue

<template functional>
 <el-popover
 placement="top-start"
 width="300"
 trigger="hover"
 popper-class="popover"
 :content="props.value">
 <span slot="reference" class="popover-txt">{{props.value}}</span>
 </el-popover>
</template>
<style scoped>
.popover-txt{
 overflow:hidden;
 text-overflow:ellipsis;
 white-space:nowrap;
 display: block;
 cursor: pointer;
}
</style>

從以上代碼中可以看出,我既使用了基于render函數(shù)類型的函數(shù)式組件也使用了基于模板的函數(shù)式組件,主要是為了在封裝時(shí)的方便,畢竟使用render這個(gè)最接近編譯器的函數(shù)還是有點(diǎn)麻煩的,不如基于模板的函數(shù)式組件來的方便。

4、使用封裝后的表格table組件:

<template>
 <div style="margin: 20px;">
 <el-button type="primary" v-if="excelExport" @click="download">獲取勾選的表格數(shù)據(jù)</el-button>
 <Table :config="config" ref="table" />
 </div>
</template>

<script>
import Table from '@/components/table'

export default {
 components: {
 Table,
 },
 data() {
 return {
 config: {
 headers: [
  {prop: 'contractCode', name: '業(yè)務(wù)編號(hào)', attrs: {width: 200, align: 'center'}},
  {prop: 'payeeAcctName', name: '收款賬戶名', type: 'Link', url: 'otherElTable', attrs: {width: 260, align: 'right'}},
  {prop: 'tradeAmt', name: '付款金額', type: 'Currency'},
  {prop: 'status', name: '操作狀態(tài)', type: 'Enum', Enum: {name: 'order'}},
  {prop: 'statistic', name: '預(yù)警統(tǒng)計(jì)', type: 'Loop', Loop: (val) => this.loop(val)},
  {prop: 'reason', name: '原因', type: 'Popover'},
  {prop: 'payTime', name: '付款時(shí)間', type: "Date", format: 'yyyy-MM-dd hh:mm:ss'}, //不設(shè)置format的話,日期格式默認(rèn)為yyyy/MM/dd
  {prop: 'monitorStatus', name: '當(dāng)前監(jiān)控狀態(tài)', type: 'Enum', Enum: {name: 'monitor'}},
 ].concat(this.getActions()),
 tableData: [
  {id: 1, contractCode: '', payeeAcctName: '中國(guó)銀行上海分行', tradeAmt: '503869', status: '00', payTime: 1593585652530, 
  statistic:[
  {level: 3, total: 5},
  {level: 2, total: 7},
  {level: 1, total: 20},
  {level: 0, total: 0}
  ]
  },
  {id: 2, contractCode: 'GLP-YG-B3-1111', payeeAcctName: '中國(guó)郵政上海分行', tradeAmt: '78956.85', status: 'CREATED', payTime: 1593416718317, 
  reason: 'Popover的屬性與Tooltip很類似,它們都是基于Vue-popper開發(fā)的,因此對(duì)于重復(fù)屬性,請(qǐng)參考Tooltip的文檔,在此文檔中不做詳盡解釋。',
  },
  {id: 3, contractCode: 'HT1592985730310', payeeAcctName: '招商銀行上海支行', tradeAmt: '963587123', status: 'PASS', payTime: 1593420950772, monitorStatus: '01'},
  {id: 4, contractCode: 'pi239', payeeAcctName: '廣州物流有限公司', tradeAmt: '875123966', status: 'REJECT', payTime: 1593496609363},
  {id: 5, contractCode: '0701001', payeeAcctName: '建設(shè)銀行上海分賬', tradeAmt: '125879125', status: 'REFUSE', payTime: 1593585489177},
 ],
 hasCheckbox: true,
 },
 status: "01",
 permission: ["handle", "pass", "refuse", "reApply", 'export']
 }
 },
 computed: {
 handle() {
 return this.permission.some(n => n == "handle");
 },
 pass() {
 return this.permission.some(n => n == "pass");
 },
 reject() {
 return this.permission.some(n => n == "reject");
 },
 refuse() {
 return this.permission.some(n => n == "refuse");
 },
 excelExport(){
 return this.permission.some(n => n == "handle") && this.permission.some(n => n == "export");
 },
 },
 methods: {
 getActions(){
 return {prop: 'action', name: '操作', type: "Action", value: [
 {label: "查看", click: data => {console.log(data)}},
 {label: "辦理", click: data => {}, filter: ({status}) => status == 'CREATED' && this.handle},
 {label: "通過", click: data => {}, filter: ({status}) => status == 'PASS' && this.pass},
 {label: "駁回", click: data => {}, filter: ({status}) => status == 'REJECT' && this.reject},
 {label: "拒絕", click: data => {}, filter: ({status}) => status == 'CREATED' && this.refuse},
 ]}
 },
 loop(val){
 let str = '';
 val.forEach(t => {
 str += '<span style="margin-right:5px;">' + t.total + '</span>';
 })
 return str;
 },
 download(){
 console.log(this.$refs.table.getChecked())
 },
 },
};
</script>
<style>
.action span{margin-right:10px;color:#359C67;cursor: pointer;}
</style>

關(guān)于金額千分位和時(shí)間戳格式化的實(shí)現(xiàn),這里就不再貼代碼了,可自行實(shí)現(xiàn)。

總結(jié)

到此這篇關(guān)于封裝Vue Element的table表格組件的文章就介紹到這了,更多相關(guān)封裝Vue Element table表格組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue3中使用pinia(大菠蘿)狀態(tài)管理倉(cāng)庫(kù)的項(xiàng)目實(shí)踐

    vue3中使用pinia(大菠蘿)狀態(tài)管理倉(cāng)庫(kù)的項(xiàng)目實(shí)踐

    本文主要介紹了vue3中使用pinia(大菠蘿)狀態(tài)管理倉(cāng)庫(kù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Vue計(jì)算屬性中reduce方法實(shí)現(xiàn)遍歷方式

    Vue計(jì)算屬性中reduce方法實(shí)現(xiàn)遍歷方式

    這篇文章主要介紹了Vue計(jì)算屬性中reduce方法實(shí)現(xiàn)遍歷方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 詳解Vue如何在頁面刷新時(shí)進(jìn)行重定向

    詳解Vue如何在頁面刷新時(shí)進(jìn)行重定向

    這篇文章主要為大家詳細(xì)介紹了Vue如何在頁面刷新時(shí)進(jìn)行重定向,文中的示例代碼簡(jiǎn)潔易懂,具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下
    2025-01-01
  • Vue3更高效的構(gòu)建工具Vite使用指南

    Vue3更高效的構(gòu)建工具Vite使用指南

    這篇文章主要給大家介紹了關(guān)于Vue3更高效的構(gòu)建工具Vite使用的相關(guān)資料,Vite是一種面向現(xiàn)代瀏覽器的一個(gè)更輕、更快的前端構(gòu)建工具,能夠顯著提升前端的開發(fā)體驗(yàn),需要的朋友可以參考下
    2023-10-10
  • vue2和vue3子組件父組件之間的傳值方法

    vue2和vue3子組件父組件之間的傳值方法

    在組件化開發(fā)的過程中難免會(huì)遇見子組件和父組件之間的通訊那么這里講關(guān)于vue2和vue3不同的通訊方式,文中有詳細(xì)的代碼示例供大家參考,感興趣的同學(xué)可以閱讀下
    2023-05-05
  • vue3循環(huán)設(shè)置ref并獲取的解決方案

    vue3循環(huán)設(shè)置ref并獲取的解決方案

    我們?cè)谄綍r(shí)做業(yè)務(wù)的時(shí)候,父子組件通信會(huì)經(jīng)常用到ref,這篇文章主要給大家介紹了關(guān)于vue3循環(huán)設(shè)置ref并獲取的解決方案,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-02-02
  • vant list組件滾動(dòng)保留滾動(dòng)條位置

    vant list組件滾動(dòng)保留滾動(dòng)條位置

    這篇文章主要介紹了vant list組件滾動(dòng)保留滾動(dòng)條位置,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Vue中使用?Aplayer?和?Metingjs?添加音樂插件的方式

    Vue中使用?Aplayer?和?Metingjs?添加音樂插件的方式

    這篇文章主要介紹了Vue中使用?Aplayer?和?Metingjs?添加音樂插件,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • vue3 源碼解讀之 time slicing的使用方法

    vue3 源碼解讀之 time slicing的使用方法

    這篇文章主要介紹了vue3 源碼解讀之 time slicing的使用方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 在vue中使用export?default導(dǎo)出的class類方式

    在vue中使用export?default導(dǎo)出的class類方式

    這篇文章主要介紹了在vue中使用export?default導(dǎo)出的class類方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評(píng)論

郯城县| 永登县| 山丹县| 抚宁县| 平安县| 建瓯市| 长岛县| 拉萨市| 南汇区| 兰考县| 游戏| 池州市| 乌拉特前旗| 东光县| 始兴县| 上饶县| 云霄县| 肥乡县| 建昌县| 杂多县| 丘北县| 阳谷县| 马鞍山市| 稷山县| 呈贡县| 婺源县| 盐津县| 桂阳县| 海晏县| 皮山县| 留坝县| 嘉峪关市| 邵阳市| 梅州市| 洮南市| 丽江市| 云阳县| 临澧县| 茂名市| 彭山县| 信阳市|