iview 升級指南 —— Button 篇

iview 在今年 7 月 28 號發佈了 3.0.0 版本,大版本升級每每意味着功能、接口的大變動。 雖然官網已經有長長的更新日誌,但看起來仍是有些抽象了, 因此我決定作個新舊版本的比較,盤點新版本到底爲咱們帶來了什麼新特性。javascript

這一篇給你們講解的,是一個很經常使用的組件 —— Buttonhtml

先看結論

新版 Button 有以下新特性:vue

  1. 支持連接模式,可經過配置 to 屬性啓動
  2. 支持獨立 ghost 屬性,樣式上可與其餘的 type 值複合
  3. 支持自定義圖標,可參考 《iview 3.x 升級盤點 —— Icon 篇》

Button 的升級相對仍是比較平滑的,須要注意兩點:java

  1. 新版本不支持 type="ghost",但可使用獨立的 ghost 屬性,因此升級前,建議全局搜索 type="ghost" 的調用
  2. 新舊版本的 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 屬性值支持 stringobject 兩種類型,iview 會優先使用 vue-router 的相關函數處理連接跳轉;當應用環境中沒有 vue-router 時,則會退化成普通的 window.location.href = this.to; 調用。 除了 toButton 還新增了 replacetarget 兩個屬性,用於補充連接的定義。replace 屬性語義與 router-link 的 replace 屬性的語義相同;target 屬性則與 a 標籤的 target 屬性相同。vue-router

總的來講,在連接模式下,你能夠把 Button 理解爲一個閹割版的 router-link 組件。api

獨立 ghost 屬性

幽靈按鈕是一個曾經被普遍討論的話題,如今已是一種很常規的設計了。這種設計指定按鈕的背景色必須是透明的,而並無定義字體、邊框樣式,但舊版本 Button 只支持一種灰色調調的 ghost:antd

新版本在這方面作了很大改進,將 ghost 樣式獨立爲一類 class,配合其餘 type 類型做爲按鈕字體、邊框顏色的補充,相得益彰,能夠看看 iview 官網提供的 示例

v2 ghost 各類形態按鈕截圖

多種色值形態的幽靈按鈕確實能夠大大提升提高實用性。曾經 1.x 版本 的 antd 也把 ghost 做爲一種 type 看待,到了2.x 版本 也抽出來作爲一個獨立特性,iview 這個改進,看來也算是有依有據,亦步亦趨了。

不過,尷尬的是,iview 順手把 default 的樣式也給改了,對於設計有較高要求的團隊得注意了:

default 按鈕 v3 vs v2

問題

好了,特性與變動都聊完了,最後咱們來看看代碼。 新版 Button 的代碼只有 116 行卻有很多值得玩味的地方:

1. 重複代碼

新版 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,abutton 包裹的內容塊完徹底全重複了, 徹底如出一轍誒。其實這一塊代碼能夠抽成一個獨立的組件,下降重複的。

另外, size 的定義,也挺尷尬的:

...
    export default {
        ...
        props: {
            ...
            size: {
                validator (value) {
                    return oneOf(value, ['small', 'large', 'default']);
                },
                default () {
                    return this.$IVIEW.size === '' ? 'default' : this.$IVIEW.size;
                }
            }
            ...
        },
        ...
    };
複製代碼

從單個組件看,是沒啥毛病,但居然能夠在代碼裏找到 16 處徹底相同的代碼,分別爲:AutoCompleteAvatarButtonGroupCascaderCheckboxGroupCheckboxColorPickerPickerInputNumberInputRadioGroupRadioSelectSpinSwitchTable...這一塊是能夠抽成一個 mixin,這錯誤犯得有點低級了。

2. 事件處理

舊版本 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>
複製代碼

handleClickLinka 標籤下被綁定了 3 次,分別帶了 exactctrlmeta 修飾符, 用於模擬普通 a 標籤的點擊效果,可是爲何不用 $event 對象的 ctrlKeymetaKey 屬性作判斷呢?我仔仔細細看了 mixinsLink 的代碼,惋惜仍是太過才疏學淺了,無法得出靠譜的結論,作了個簡單 demo 對比各類實現的效果,也沒看出個因此然。

另一個有問題的地方是 new_window 變量,其餘變量名都是駝峯的,忽然來個下劃線命名,有些突兀了。

3. 過時的 ghost 值

最後提一點, type="ghost" 已通過期了,源碼的 validator 函數也作了相應修改,如今傳進 type="ghost" 會報錯:

default 按鈕 v3 vs v2

這錯誤信息,有點「硬」了?這裏其實徹底能夠多花些心思,報個 deprecated 警告,對升級者而言會更容易分辨出該作些什麼修改。

附錄:

  1. iview 升級指南 —— Icon 篇
  2. iview 升級指南 —— Button 篇
相關文章
相關標籤/搜索