iview 在今年 7 月 28 號發佈了 3.0.0 版本,大版本升級每每意味着功能、接口的大變動。 雖然官網已經有長長的更新日誌,但看起來仍是有些抽象了, 因此我決定作個新舊版本的比較,盤點新版本到底爲咱們帶來了什麼新特性。javascript
這一篇給你們講解的,是一個很經常使用的組件 ——
Button
html
新版 Button
有以下新特性:vue
to
屬性啓動ghost
屬性,樣式上可與其餘的 type
值複合Button
的升級相對仍是比較平滑的,須要注意兩點:java
type="ghost"
,但可使用獨立的 ghost
屬性,因此升級前,建議全局搜索 type="ghost"
的調用default
樣式有些不一樣舊版本的 Button
組件只單純包裹了一個 button
標籤。 新版本 Button
新增了一個關鍵屬性:to
—— 通常狀況下,組件會渲染爲 button
標籤; 假如 to
有值,則組件會渲染爲 a
標籤。ios
雖然破壞了 Button
的語義,但這個特性還挺方便的,在過去,爲了給 a
標籤應用 Button
樣式,每每須要本身寫上 class:git
<!-- 普通 a 標籤 -->
<a class="ivu-btn ivu-btn-primary" href="/foo/bar">這是一個 a 連接</a>
<!-- router-link -->
<router-link class="ivu-btn ivu-btn-primary" to="/foo/bar">這是一個 router-link</router-link>
複製代碼
雖然能夠複用按鈕樣式,但卻喪失了 Button
的行爲,好比 loading、icon 等。新版本支持連接模式後就沒有這個問題了,一樣的邏輯,能夠寫成:github
<Button type="primary" to="/foo/bar">這是一個連接</Button>
<!-- 最終渲染爲 -->
<a class="ivu-btn ivu-btn-primary" href="/foo/bar">這是一個連接</a>
複製代碼
to
屬性值支持 string
、object
兩種類型,iview 會優先使用 vue-router
的相關函數處理連接跳轉;當應用環境中沒有 vue-router
時,則會退化成普通的 window.location.href = this.to;
調用。 除了 to
, Button
還新增了 replace
、target
兩個屬性,用於補充連接的定義。replace
屬性語義與 router-link
的 replace 屬性的語義相同;target
屬性則與 a
標籤的 target 屬性相同。vue-router
總的來講,在連接模式下,你能夠把 Button
理解爲一個閹割版的 router-link
組件。api
ghost
屬性幽靈按鈕是一個曾經被普遍討論的話題,如今已是一種很常規的設計了。這種設計指定按鈕的背景色必須是透明的,而並無定義字體、邊框樣式,但舊版本 Button
只支持一種灰色調調的 ghost:antd
新版本在這方面作了很大改進,將 ghost
樣式獨立爲一類 class,配合其餘 type
類型做爲按鈕字體、邊框顏色的補充,相得益彰,能夠看看 iview 官網提供的 示例:
多種色值形態的幽靈按鈕確實能夠大大提升提高實用性。曾經 1.x 版本 的 antd 也把 ghost 做爲一種 type 看待,到了2.x 版本 也抽出來作爲一個獨立特性,iview 這個改進,看來也算是有依有據,亦步亦趨了。
不過,尷尬的是,iview 順手把 default
的樣式也給改了,對於設計有較高要求的團隊得注意了:
好了,特性與變動都聊完了,最後咱們來看看代碼。 新版 Button
的代碼只有 116 行卻有很多值得玩味的地方:
新版 Button
的模板是這樣的:
<template>
<a v-if="to" ...>
<Icon class="ivu-load-loop" type="ios-loading" v-if="loading"></Icon>
<Icon :type="icon" :custom="customIcon" v-if="(icon || customIcon) && !loading"></Icon>
<span v-if="showSlot" ref="slot"><slot></slot></span>
</a>
<button v-else ...>
<Icon class="ivu-load-loop" type="ios-loading" v-if="loading"></Icon>
<Icon :type="icon" :custom="customIcon" v-if="(icon || customIcon) && !loading"></Icon>
<span v-if="showSlot" ref="slot"><slot></slot></span>
</button>
</template>
複製代碼
oh,a
與 button
包裹的內容塊完徹底全重複了, 徹底如出一轍誒。其實這一塊代碼能夠抽成一個獨立的組件,下降重複的。
另外, size
的定義,也挺尷尬的:
...
export default {
...
props: {
...
size: {
validator (value) {
return oneOf(value, ['small', 'large', 'default']);
},
default () {
return this.$IVIEW.size === '' ? 'default' : this.$IVIEW.size;
}
}
...
},
...
};
複製代碼
從單個組件看,是沒啥毛病,但居然能夠在代碼裏找到 16 處徹底相同的代碼,分別爲:AutoComplete
、Avatar
、ButtonGroup
、Cascader
、CheckboxGroup
、Checkbox
、ColorPicker
、Picker
、InputNumber
、Input
、RadioGroup
、Radio
、Select
、Spin
、Switch
、Table
...這一塊是能夠抽成一個 mixin,這錯誤犯得有點低級了。
舊版本 Button
只是簡單包裝了 button
標籤,因此它的事件處理 很是簡單。新版本兼容連接模式後,看起來就有些繞了:
<template>
<!-- linkUrl 是從 mixinsLink 混入的屬性 -->
<a :href="linkUrl" @click.exact="handleClickLink($event, false)" @click.ctrl="handleClickLink($event, true)" @click.meta="handleClickLink($event, true)">...</a>
<button ... @click="handleClickLink">...</button>
</template>
<script> ... export default { mixins: [ mixinsLink ], ... methods: { handleClickLink (event, new_window = false) { this.$emit('click', event); // handleCheckClick 是從 mixinsLink 混入進來的屬性 this.handleCheckClick(event, new_window); } } ... }; </script>
複製代碼
handleClickLink
在 a
標籤下被綁定了 3 次,分別帶了 exact
、ctrl
、meta
修飾符, 用於模擬普通 a
標籤的點擊效果,可是爲何不用 $event
對象的 ctrlKey
、metaKey
屬性作判斷呢?我仔仔細細看了 mixinsLink
的代碼,惋惜仍是太過才疏學淺了,無法得出靠譜的結論,作了個簡單 demo 對比各類實現的效果,也沒看出個因此然。
另一個有問題的地方是 new_window
變量,其餘變量名都是駝峯的,忽然來個下劃線命名,有些突兀了。
最後提一點, type="ghost"
已通過期了,源碼的 validator
函數也作了相應修改,如今傳進 type="ghost"
會報錯:
這錯誤信息,有點「硬」了?這裏其實徹底能夠多花些心思,報個 deprecated
警告,對升級者而言會更容易分辨出該作些什麼修改。
附錄: