ant-design-vue中的table自定義格式渲染解析
ant-design-vue中table自定義格式渲染
一般業(yè)務(wù)開(kāi)發(fā)中,難免會(huì)遇到將一些狀態(tài)值(如 0 / 1)轉(zhuǎn)化為相應(yīng)的描述(如 關(guān)閉 / 開(kāi)啟),也可能是對(duì)日期時(shí)間的格式化,如下兩圖轉(zhuǎn)化前后對(duì)比:


開(kāi)始之前,需要注意的是,定義的 columns 一定要寫在 data 中,否則在加載過(guò)程中由于渲染順序會(huì)導(dǎo)致其中的渲染函數(shù)無(wú)法識(shí)別。
有兩種方式修改:
1、直接調(diào)用對(duì)應(yīng)插槽模板
<template>
<div class="vehicle-list">
<a-table :columns="columns" :data-source="data" bordered>
<template slot="tradeState" slot-scope="state">
{{ state === 1 ? '交易完成' : (state === 0 ? '等待交易' : '交易失敗') }}
</template>
<template slot="tradeTime" slot-scope="time">
{{ timeFormat(time) }}
</template>
</a-table>
</div>
</template>
<script>
import moment from 'moment'
const columns = [
{
title: '交易狀態(tài)',
dataIndex: 'tradeState',
// customRender: 'tradeState' -> 自定義 slot 屬性名,對(duì)應(yīng)模版中的 slot 屬性,即這里自定義為啥,對(duì)應(yīng)模版中的 slot 就要等于啥
// 模板中對(duì)應(yīng)的 slot-scope 屬性可以用來(lái)傳遞三個(gè)參數(shù)(val,row,index),分別是當(dāng)前值、當(dāng)前行數(shù)據(jù)和當(dāng)前索引
scopedSlots: { customRender: 'tradeState' }
},
{
title: '交易時(shí)間',
dataIndex: 'tradeTime',
scopedSlots: { customRender: 'tradeTime' }
}
]
const data = [
{
key: '1',
tradeState: 1,
tradeTime: '2020-11-01T12:50:19+08:00'
},
{
key: '2',
tradeState: -1,
tradeTime: '2020-11-02T18:06:32+08:00'
},
{
key: '3',
tradeState: 0,
tradeTime: '2020-11-03T08:25:03+08:00'
}
]
export default {
name: 'VehicleList',
data () {
return {
data,
columns
}
},
methods: {
timeFormat (val) { // 時(shí)間格式化函數(shù)
return moment(val).format('YYYY-MM-DD HH:mm:ss')
}
}
}
</script>
2、指定渲染函數(shù)
<template>
<div class="vehicle-list" style="width: 50%">
<a-table :columns="columns" :data-source="data" bordered></a-table>
</div>
</template>
<script>
import moment from 'moment'
const columns = [
{
title: '交易狀態(tài)',
dataIndex: 'tradeState',
customRender: (state) => { // customRender屬性是一個(gè)方法,可接收三個(gè)參數(shù)(val,row,index),分別是當(dāng)前值、當(dāng)前行數(shù)據(jù)和當(dāng)前索引,與方式 1 中模版的 slot-scope 屬性傳參類似
return state === 1 ? '交易完成' : (state === 0 ? '等待交易' : '交易失敗')
}
},
{
title: '交易時(shí)間',
dataIndex: 'tradeTime',
customRender: (time) => moment(time).format('YYYY-MM-DD HH:mm:ss')
}
]
const data = [
{
key: '1',
tradeState: 1,
tradeTime: '2020-11-01T12:50:19+08:00'
},
{
key: '2',
tradeState: -1,
tradeTime: '2020-11-02T18:06:32+08:00'
},
{
key: '3',
tradeState: 0,
tradeTime: '2020-11-03T08:25:03+08:00'
}
]
export default {
name: 'VehicleList',
data () {
return {
data,
columns
}
}
}
</script>
對(duì)比以上,可以看出方式2代碼更加簡(jiǎn)潔,且易讀性更好。
ant-design-vue快速上手指南+排坑
公司要開(kāi)發(fā)一個(gè)后臺(tái)管理系統(tǒng),對(duì)于UI庫(kù)的選擇上選擇了顏值爆表的Ant-Design-Vue作為整個(gè)項(xiàng)目UI庫(kù),但誰(shuí)曾想,暗中的坑一個(gè)接一個(gè),文檔也不怎么詳細(xì),可能習(xí)慣了element-ui的掘友們也許不怎么好適應(yīng),本文就帶大家一起學(xué)習(xí)如何高效使用Ant-Design-Vue。
NO.1 表單組件
首先就來(lái)說(shuō)說(shuō)最常用的Form組件的正確使用姿勢(shì):
先來(lái)看官方一段話述:
第一、我們不推薦在Form中使用雙向綁定,同一份數(shù)據(jù)可能在多處使用,如果使用雙向綁定,那么數(shù)據(jù)的修改會(huì)同時(shí)同步到各個(gè)組件,但這并不是我們想要的, 你應(yīng)該在表單提交成功或失敗或確認(rèn)時(shí)同步數(shù)據(jù),使用非雙向綁定的表單,你會(huì)擁有最大限度的控制數(shù)據(jù)修改/同步的權(quán)限。
第二、如果你不使用表單的自動(dòng)校驗(yàn)/收集功能,即沒(méi)有使用v-decorator修飾過(guò)的組件,你依然可以使用v-model
看了官方的建議后,我們愉快的使用v-decorator修飾input組件,代碼如下:
<a-form-item>
<a-input
placeholder="賬號(hào)"
v-decorator="['account',{rules: [{ required: true,whitespace:true,message: '請(qǐng)輸入您的登陸賬號(hào)' }]}]"
/>
</a-form-item>劃重點(diǎn):
v-decorator里的account可以理解為input的name值,后面{}對(duì)象可以配置校驗(yàn)規(guī)則,初始值等參數(shù),這里需要注意的是使用了v-decorator的組件無(wú)法使用v-model,也無(wú)法設(shè)置value等與值有關(guān)的屬性,否則報(bào)錯(cuò)
v-decorator會(huì)自動(dòng)收集你表單里的數(shù)據(jù)到form對(duì)象里,所以別忘了在data中加上這句代碼:
form: this.$form.createForm(this)

模板中這么寫:

如何自定義表單校驗(yàn)規(guī)則
這里拿確認(rèn)密碼舉例:
<a-input
type="password"
v-decorator="['new_password',{rules:[{required: true,whitespace:true,message: '請(qǐng)輸入新密碼'},{validator: handlePass}]}]"
/>
<a-input
type="password"
v-decorator="['confirm_password',{rules:[{required: true,whitespace:true,message: '請(qǐng)重復(fù)新密碼'},{validator:handleConfirmPass}]}]"
/>這里我們使用validator校驗(yàn)器自定義函數(shù)
handlePass(rule, value, callback) {
this.password = value;
callback();
},
handleConfirmPass(rule, value, callback) {
if (this.password && this.password !== value) {
callback('與新密碼輸入不一致');
}
callback();
},這里需要注意callback()必須調(diào)用
這里的value就是對(duì)應(yīng)表單輸入了的值,然后知道了這些我們就可以寫我們自己的業(yè)務(wù)邏輯了
做好的效果如圖:

表單回顯
我們?cè)谧鼍庉嫊r(shí)首先需要通過(guò)后端接口讀取到之前的數(shù)據(jù),但是因?yàn)楝F(xiàn)在沒(méi)有了v-model,那么我們?cè)撛趺崔k?
可以調(diào)用form對(duì)象中的setFieldsValue把后端返回的對(duì)象直接設(shè)置上去,如果是在mounted方法里必須加上$nextTick,不然會(huì)拋出警告說(shuō)我們?cè)诒韱挝翠秩竞弥敖o予了數(shù)據(jù)
代碼如圖:

圖中setFieldsInitialValue是設(shè)置表單初始值,如果表單中有重置按鈕,就需要設(shè)置上,重置按鈕調(diào)用this.form.resetFields()就可以重置form表單了
這個(gè)setFieldsValue方法會(huì)把傳進(jìn)去的對(duì)象的key和模板中v-decorator中的第一個(gè)參數(shù)比較,會(huì)自動(dòng)把對(duì)應(yīng)的值set進(jìn)去。
提交表單

按鈕加上html-type="submit"后點(diǎn)擊會(huì)觸發(fā)這個(gè)方法,這個(gè)方法校驗(yàn)表單中所有必填項(xiàng)沒(méi)有問(wèn)題后會(huì)自動(dòng)幫我們把表單中所有帶有v-decorator修飾的組件的值和name序列化好,我們就可以直接傳給后端了。
NO.2 表格(Table)
我們的模板可以這么寫:

ant-design-vue的表格自帶分頁(yè),接下來(lái)我把上圖中的參數(shù)挨個(gè)解釋下,columns是單元格信息,我們可以把他導(dǎo)出為一個(gè)數(shù)組,如下圖:

這里的title是用戶看到的文字,dataIndex要和后臺(tái)傳過(guò)來(lái)的字段一致,不然數(shù)據(jù)不會(huì)顯示出來(lái),其次還提供了customRender和scopedSlots兩種方式自定義內(nèi)容,這里使用了第一種方式,但值得一提的是如果使用的是slot-scope方式,在模板中定義一個(gè)點(diǎn)擊事件,想要獲取到當(dāng)前行的數(shù)據(jù)時(shí),一定一定不要加dataIndex屬性,否則會(huì)是undefined
看一個(gè)scopedSlots使用的例子:


可以看到上面定義columns時(shí)給action沒(méi)有加dataIndex
我們繼續(xù)看dataSource是什么,他就是你給table傳遞的數(shù)據(jù)
rowKey可以理解為時(shí)循環(huán)時(shí)需要的key(必有)pagination初始化一個(gè)空對(duì)象scroll定義表格可以橫向滾動(dòng)handleTableChange是當(dāng)分頁(yè)數(shù)據(jù)發(fā)生改變時(shí)拋出的事件
為了簡(jiǎn)化操作,我這里封裝了一個(gè)mixin,當(dāng)頁(yè)面中有table時(shí)直接混入mixin就支持分頁(yè)和拉取數(shù)據(jù)的邏輯了,代碼如下:
export const mixin = {
data() {
return {
pagination: {},
data: [],
};
},
methods: {
handleTableChange(pagination) {
const pager = {...this.pagination};
pager.current = pagination.current;
this.pagination = pager;
this.loadData({
page: pagination.current
});
},
async loadData(params = {}) {
try {
const {data: table_data, total, per_page} = await this.loadMethod('flush' in params ? {page: 1} : {page: 1, ...params});
const pagination = {...this.pagination};
pagination.total = total;
pagination.pageSize = per_page;
'flush' in params && (pagination.current = 1);
this.data = table_data;
this.pagination = pagination;
} catch (e) {
console.log(e);
}
}
}
};
flush用于標(biāo)識(shí)是否是插入新數(shù)據(jù)或者刪除了數(shù)據(jù),如果是我們直接把page重置為1返回第一頁(yè)
我們?cè)陧?yè)面使用只需要以下幾行代碼:
import { getLog } from '@/api/api';
import { mixin } from '@/mixins';
export default {
name: "log",
mixins: [mixin],
data() {
return {
columns,
loadMethod: getLog
};
},
mounted() {
this.loadData();
}
};
這樣其他類似的組件也可以直接復(fù)用本邏輯。
NO.3 Spin組件
我們平時(shí)在后臺(tái)管理系統(tǒng)中,ajax請(qǐng)求過(guò)程中都會(huì)出現(xiàn)全屏加載提示的遮罩層,做這個(gè)功能時(shí)我想到了這個(gè)組件,然后去官方文檔查看,看到了如下圖的操作方式:

然后粘貼到代碼中,各種操作,沒(méi)有任何反應(yīng),甚至有時(shí)候還來(lái)點(diǎn)小報(bào)錯(cuò),Spin組件肯定是引入了,反正就是最后怎么操作都沒(méi)成功,無(wú)奈之下,自己用了他的樣式寫了個(gè)Vue的Spin插件:
我們首先新建Loading.vue
<template>
<div v-if="show" class="loading-container">
<div class="loading-mask"></div>
<div class="loading-content">
<a-spin tip="正在加載數(shù)據(jù)中..." size="large">
</a-spin>
</div>
</div>
</template>
<script>
export default {
name: 'Loading',
props: {
show: Boolean,
},
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
.loading-container{
position: relative;
text-align: center;
z-index:9999;
.loading-mask{
position: fixed;
top:0;
bottom:0;
left:0;
right:0;
background-color:rgba(0,0,0,.7);
}
.loading-content{
position: fixed;
left: 50%;
top: 50%;
z-index: 300;
transform: translate(-50%,-50%);
text-align: center;
color:#fff;
}
}
</style>
然后再新建Loading.js
import Vue from 'vue';
import loadingComponent from './Loading.vue';
const LoadingConstructor = Vue.extend(loadingComponent);
const instance = new LoadingConstructor({
el: document.createElement('div')
});
instance.show = false; // 默認(rèn)隱藏
const loading = {
show() { // 顯示方法
instance.show = true;
document.body.appendChild(instance.$el);
},
hide() { // 隱藏方法
instance.show = false;
}
};
export default {
install() {
if (!Vue.$loading) {
Vue.$loading = loading;
}
Vue.mixin({
created() {
this.$loading = Vue.$loading;
}
});
}
};
然后在main.js中
import loading from '@/components/Loading/loading.js'; Vue.use(loading);
然后我們就可以愉快的調(diào)用了:
Vue.$loading.show();
打包優(yōu)化
首先就是用官方快速上手中提供的按需加載,這里不再贅述,使用之后還存在以下問(wèn)題:
里面的moment.js,還有l(wèi)odash,還有icon的dist居然占用了我們500KB的空間,這不能忍,那怎么辦呢?
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
我們首先忽略掉語(yǔ)言包,然后看看圖標(biāo)怎么優(yōu)化:

config.resolve.alias
.set('@', resolve('src'))
.set('@ant-design/icons/lib/dist$',resolve('src/icon.js'))
我們還需要在src文件夾下面加一個(gè)文件 icons.js
//自己項(xiàng)目里面用到的Icon
export {default as UserOutline} from '@ant-design/icons/lib/outline/UserOutline';
export {default as CloseCircleFill} from '@ant-design/icons/lib/fill/CloseCircleFill';
export {default as InfoCircleFill} from '@ant-design/icons/lib/fill/InfoCircleFill';
export {default as CheckCircleFill} from '@ant-design/icons/lib/fill/CheckCircleFill';
我們還可以開(kāi)啟gzip壓縮等,使用DLL優(yōu)化我們的打包速度,這些在這里就不再贅述了,社區(qū)有很多類似的貼子。
結(jié)語(yǔ)
那么對(duì)于ant-design-vue使用的前兩天感覺(jué)不怎么順手,現(xiàn)在只能說(shuō)真香
其實(shí)這個(gè)UI庫(kù)用習(xí)慣之后會(huì)發(fā)現(xiàn)好像Form表單的設(shè)計(jì)其實(shí)比v-model更好用,哈哈
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue實(shí)現(xiàn)將時(shí)間戳轉(zhuǎn)換成日期格式
這篇文章主要介紹了vue實(shí)現(xiàn)將時(shí)間戳轉(zhuǎn)換成日期格式方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,2023-10-10
vue3.0中使用Element-Plus中Select下的filter-method屬性代碼示例
這篇文章主要給大家介紹了關(guān)于vue3.0中使用Element-Plus中Select下的filter-method屬性的相關(guān)資料,Filter-method用法是指從一組數(shù)據(jù)中選擇滿足條件的項(xiàng),文中通過(guò)圖文以及代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
使用 Vue 實(shí)現(xiàn)一個(gè)虛擬列表的方法
這篇文章主要介紹了使用 Vue 實(shí)現(xiàn)一個(gè)虛擬列表的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08
解決vite.config.js無(wú)法使用__dirname的問(wèn)題
這篇文章主要介紹了解決vite.config.js無(wú)法使用__dirname的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10

