<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
一般業務開發中,難免會遇到將一些狀態值(如 0 / 1)轉化為相應的描述(如 關閉 / 開啟),也可能是對日期時間的格式化,如下兩圖轉化前後對比:
開始之前,需要注意的是,定義的 columns 一定要寫在 data 中,否則在載入過程中由於渲染順序會導致其中的渲染函數無法識別。
有兩種方式修改:
<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: '交易狀態', dataIndex: 'tradeState', // customRender: 'tradeState' -> 自定義 slot 屬性名,對應模版中的 slot 屬性,即這裡自定義為啥,對應模版中的 slot 就要等於啥 // 模板中對應的 slot-scope 屬性可以用來傳遞三個引數(val,row,index),分別是當前值、當前行資料和當前索引 scopedSlots: { customRender: 'tradeState' } }, { title: '交易時間', 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) { // 時間格式化函數 return moment(val).format('YYYY-MM-DD HH:mm:ss') } } } </script>
<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: '交易狀態', dataIndex: 'tradeState', customRender: (state) => { // customRender屬性是一個方法,可接收三個引數(val,row,index),分別是當前值、當前行資料和當前索引,與方式 1 中模版的 slot-scope 屬性傳參類似 return state === 1 ? '交易完成' : (state === 0 ? '等待交易' : '交易失敗') } }, { title: '交易時間', 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>
對比以上,可以看出方式2程式碼更加簡潔,且易讀性更好。
公司要開發一個後臺管理系統,對於UI庫的選擇上選擇了顏值爆表的Ant-Design-Vue作為整個專案UI庫,但誰曾想,暗中的坑一個接一個,檔案也不怎麼詳細,可能習慣了element-ui的掘友們也許不怎麼好適應,本文就帶大家一起學習如何高效使用Ant-Design-Vue。
首先就來說說最常用的Form元件的正確使用姿勢:
先來看官方一段話述:
第一、我們不推薦在Form中使用雙向繫結,同一份資料可能在多處使用,如果使用雙向繫結,那麼資料的修改會同時同步到各個元件,但這並不是我們想要的, 你應該在表單提交成功或失敗或確認時同步資料,使用非雙向繫結的表單,你會擁有最大限度的控制資料修改/同步的許可權。
第二、如果你不使用表單的自動校驗/收集功能,即沒有使用v-decorator修飾過的元件,你依然可以使用v-model
看了官方的建議後,我們愉快的使用v-decorator修飾input元件,程式碼如下:
<a-form-item> <a-input placeholder="賬號" v-decorator="['account',{rules: [{ required: true,whitespace:true,message: '請輸入您的登陸賬號' }]}]" /> </a-form-item>
劃重點:
v-decorator裡的account可以理解為input的name值,後面{}物件可以設定校驗規則,初始值等引數,這裡需要注意的是使用了v-decorator的元件無法使用v-model,也無法設定value等與值有關的屬性,否則報錯
v-decorator會自動收集你表單裡的資料到form物件裡,所以別忘了在data中加上這句程式碼:
form: this.$form.createForm(this)
模板中這麼寫:
如何自定義表單校驗規則
這裡拿確認密碼舉例:
<a-input type="password" v-decorator="['new_password',{rules:[{required: true,whitespace:true,message: '請輸入新密碼'},{validator: handlePass}]}]" /> <a-input type="password" v-decorator="['confirm_password',{rules:[{required: true,whitespace:true,message: '請重複新密碼'},{validator:handleConfirmPass}]}]" />
這裡我們使用validator校驗器自定義函數
handlePass(rule, value, callback) { this.password = value; callback(); }, handleConfirmPass(rule, value, callback) { if (this.password && this.password !== value) { callback('與新密碼輸入不一致'); } callback(); },
這裡需要注意callback()必須呼叫
這裡的value就是對應表單輸入了的值,然後知道了這些我們就可以寫我們自己的業務邏輯了
做好的效果如圖:
表單回顯
我們在做編輯時首先需要通過後端介面讀取到之前的資料,但是因為現在沒有了v-model,那麼我們該怎麼辦?
可以呼叫form物件中的setFieldsValue把後端返回的物件直接設定上去,如果是在mounted方法裡必須加上$nextTick,不然會丟擲警告說我們在表單未渲染好之前給予了資料
程式碼如圖:
圖中setFieldsInitialValue是設定表單初始值,如果表單中有重置按鈕,就需要設定上,重置按鈕呼叫this.form.resetFields()就可以重置form表單了
這個setFieldsValue方法會把傳進去的物件的key和模板中v-decorator中的第一個引數比較,會自動把對應的值set進去。
提交表單
按鈕加上html-type="submit"後點選會觸發這個方法,這個方法校驗表單中所有必填項沒有問題後會自動幫我們把表單中所有帶有v-decorator修飾的元件的值和name序列化好,我們就可以直接傳給後端了。
我們的模板可以這麼寫:
ant-design-vue的表格自帶分頁,接下來我把上圖中的引數挨個解釋下,columns是單元格資訊,我們可以把他匯出為一個陣列,如下圖:
這裡的title是使用者看到的文字,dataIndex要和後臺傳過來的欄位一致,不然資料不會顯示出來,其次還提供了customRender和scopedSlots兩種方式自定義內容,這裡使用了第一種方式,但值得一提的是如果使用的是slot-scope方式,在模板中定義一個點選事件,想要獲取到當前行的資料時,一定一定不要加dataIndex屬性,否則會是undefined
看一個scopedSlots使用的例子:
可以看到上面定義columns時給action沒有加dataIndex
我們繼續看dataSource是什麼,他就是你給table傳遞的資料
rowKey
可以理解為時迴圈時需要的key
(必有)pagination
初始化一個空物件scroll
定義表格可以橫向捲動handleTableChange
是當分頁資料發生改變時丟擲的事件為了簡化操作,我這裡封裝了一個mixin,當頁面中有table時直接混入mixin就支援分頁和拉取資料的邏輯了,程式碼如下:
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用於標識是否是插入新資料或者刪除了資料,如果是我們直接把page重置為1返回第一頁
我們在頁面使用只需要以下幾行程式碼:
import { getLog } from '@/api/api'; import { mixin } from '@/mixins'; export default { name: "log", mixins: [mixin], data() { return { columns, loadMethod: getLog }; }, mounted() { this.loadData(); } };
這樣其他類似的元件也可以直接複用本邏輯。
我們平時在後臺管理系統中,ajax請求過程中都會出現全螢幕載入提示的遮罩層,做這個功能時我想到了這個元件,然後去官方檔案檢視,看到了如下圖的操作方式:
然後貼上到程式碼中,各種操作,沒有任何反應,甚至有時候還來點小報錯,Spin元件肯定是引入了,反正就是最後怎麼操作都沒成功,無奈之下,自己用了他的樣式寫了個Vue的Spin外掛:
我們首先新建Loading.vue
<template> <div v-if="show" class="loading-container"> <div class="loading-mask"></div> <div class="loading-content"> <a-spin tip="正在載入資料中..." 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; // 預設隱藏 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);
然後我們就可以愉快的呼叫了:
Vue.$loading.show();
首先就是用官方快速上手中提供的按需載入,這裡不再贅述,使用之後還存在以下問題:
裡面的moment.js,還有lodash,還有icon的dist居然佔用了我們500KB的空間,這不能忍,那怎麼辦呢?
new webpack.IgnorePlugin(/^./locale$/, /moment$/),
我們首先忽略掉語言套件,然後看看圖示怎麼優化:
config.resolve.alias .set('@', resolve('src')) .set('@ant-design/icons/lib/dist$',resolve('src/icon.js'))
我們還需要在src資料夾下面加一個檔案 icons.js
//自己專案裡面用到的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';
我們還可以開啟gzip壓縮等,使用DLL優化我們的打包速度,這些在這裡就不再贅述了,社群有很多類似的貼子。
那麼對於ant-design-vue使用的前兩天感覺不怎麼順手,現在只能說真香
其實這個UI庫用習慣之後會發現好像Form表單的設計其實比v-model更好用,哈哈
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45