爲Vue2集成UIkit

引言:Vue只是爲我們提供了一個很優秀的前端組件式開發框架,但單純依靠Vue是做不出一個漂亮的網頁應用的,甚至連“不難看”這個標準都達不到。這個時候藉助界面框架UIkit能夠很好地解決這一問題。
本文出自《Vue2實踐揭祕》一書。

  在實際開發中,還有很多常用組件,例如,分頁、按鈕、輸入框、導航欄、日期/時間選擇器、圖片輸入,等等。很明顯的是這些組件的通用性已不單單存在於一個項目內,而是所有的項目都需要!這是個比拼開發速度的年代,我們已經沒有時間重複發明輪子了,最正確的選擇是使用界面框架,例如Bootstrap、UIkit、Foundation等來代替這種大量的重複性極強的界面樣式開發工作。

UIkit

  Bootstrap已經有很多年曆史了,在業界的應用也相當普遍,無論是前端開發或者後端開發,爲了能快速做一個不算太難看的界面,它自然成爲衆多工程師的選擇,包括我。多年下來,Bookstrap的改進實在是太緩慢了。不客氣地說,它基本上就沒讓我們這些用戶感覺它改進過,同質化嚴重,功能性組件一直不見增加,等等,都讓我們只能是痛並用着。
  UIkit給我們帶來了福音,無論從界面上的樣式,還是實用組件的數目,甚至到易用性來說都要比Bootstrap好上一個層次。唯一的缺陷是它出生得比較晚,可選的主題樣式資源不多,畢竟還需要時間讓第三方社區來推動發展。但用它來做一個漂亮的交互性強的應用絕對是一個最佳的推薦方案。
  Vue社區上也有一些包裝UIkit的庫,如vuikit,但它的文檔實在太少了,甚至從一開始的安裝配套都做得非常差,基本上是脫離了UIkit的核心樣式包和核心腳本編寫的。雖然努力可嘉,但這種功能性複製的包建議還是不要用,前端最耗不起的就是編譯包的大小。每個引入的第三方包我們都得吝嗇地測算一下得失,即使webpack可以用chuck來分包,但也不能濫用,否則加載速度緩慢就是破壞使用體驗的最大因素。

安裝

  雖然在AngularJS、React和Vue的項目中jQuery從來都是一個不受歡迎的庫。首先是它編譯出來後就非常大,而且影響我們的MVVM思維,容易因爲圖方便而又回到jQuery那種直接操控DOM的死路上去。但jQuery的強大在於它的普及性,幾乎我們能找到的很多優秀小組件都會有jQuery版本,甚至只有jQuery的版本。而UIkit正是其中一員,不能抗拒的話也只能學會享受。我們得同時安裝jQuery、UIkit兩個庫:

$ npm i jquery uikit -D

配置

  我們需要將jQuery和UIkit的引用以及一些字體的引用配置添加到webpack中(UIkit內置引用了Fontawesome字體庫),確保已安裝了url-loader這個庫,如果沒有安裝的話用以下指令進行安裝:

$ npm i url-loader --D

  在webpack.config.js的module.rules配置中加入字體引用配置:

rules: [
    // ... 省略
    {        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,        loader: 'url',        query: {            limit: 10000,            name: '[name].[hash:7].[ext]'
        }
    }
]

  當然,如果你採用vue-cli webpack模板來構造項目的話,可以跳過以上的配置。
  UIkit的運行主要依賴於一個主樣式文件uikit.css、一個主題文件uikit.almost-flat.css(主題文件內置有三個可選項)和一個腳本文件uikit.js。使用UIkit時,需要在代碼中同時import它們才能讓webpack在編譯時正確地引用。界面包都是全局性的,那麼可以選擇在main.js文件一開始加入引用:

import 'jquery'import 'uikit'import 'uikit/dist/css/uikit.almost-flat.css'

  這樣寫就違反了在第2章工程化Vue.js開發中的一個配置約定,我們不應該將“庫”或“依賴包”以全路徑方式引入到代碼文件中,而應該用webpack的resolve配置項,用別名來代替全路徑。以下是在webpack中配置UIkit的樣式引用別名:

resolve: {    alias: {        'vue$': 'vue/dist/vue',        'uikit-css$': 'uikit/dist/css/uikit.almost-flat.css'
    }
}

  在main.js代碼內引入UIkit,代碼就變爲:

import 'jquery'import 'uikit'import "uikit-css"

製作UIkit的Vue插件

  上述的寫法還是不夠DRY,爲了使用一個包就得引入多個不同的依賴庫,這種做法實在很難看,此時我們可以選擇一個Vue的最佳做法,就是用插件形式來包裝這種零碎化的引入方式。在src根目錄下新建一個uikit.js的文件,然後用Vue的插件格式來進行包裝。以下代碼中直接向Vue實例注入了UIkit的一些常用的幫助方法:

import 'jquery'import 'uikit'import 'uikit-css'export default (Vue, options) {    // 向實例注入UIkit的對話框類方法
    Vue.prototype.$ui = {
        alert: UIkit.modal.alert
        confirm: UIkit.modal.confirm,
        prompt: UIkit.modal.prompt,
        block: UIkit.modal.block
    }
}

  完成uikit.js的編寫就可以改寫main.js的內容了:

import UIkit from './uikit'Vue.use(UIKit)

  由於對Vue.prototype進行了擴展,那麼就可以像vue-resource那樣在每個Vue實例內的this方法中注入一個$ui對象,用以下方法來顯示簡單的對話框:

methods: {
    delItem() {        this.$ui.confirm('您確認要刪除以下的數據嗎?', () => {            // 這裏編寫對數據進行刪除的代碼
        })
    }
}

  

       圖片描述

  上述的confirm方法有一個明顯的弱點,就是在回調時this上下文會指向window而不是Vue實例本身,這樣的話對於編碼的使用體驗就很差了。我們可以在插件內對confirm做一個修飾,將回調方法的this重新指向Vue實例:

Vue.prototype.$ui = {   // ... 省略
   confirm (question,callback,cancelCallback,options) {
        UIkit.confirm(question,        callback || callback.apply(this),
        cancelCallback || cancelCallback.apply(this),
        options)
   }

}

  apply函數是ECMA JavaScript的標準函數,用於更改調用方法上傳遞的上下文對象。上述代碼就是將回調函數的上下文強制替換爲當前的Vue實例,避免了回調上下文丟失而需要手工去定義變量,“hold住”原有this上下文的痛苦。

關於apply函數詳細說明可以參考以下鏈接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply。

  現在的代碼是不是感覺乾淨多了?那麼回過頭來看Vue的插件,在這裏面我們不僅可以像上述代碼那樣單純地對Vue實例進行擴展,還可以進行更多的全局化的處理。當然這裏的全局是指這個插件庫被引入Vue並調用use方法後,例如,我們可以將一些必要的組件或者指令混入插件方法內:

export default = (Vue, options) => {  // 1. 注入全局化的方法
  Vue.myGlobalMethod = () => {    // ...
  }  // 2. 進行必要組件的註冊
  Vue.component('html-editor', { 
    HtmlEditor
  })  // 3. 註冊一個全局化的指令標記
  Vue.directive('sortable', {
    bind (el, binding, vnode, oldVnode) {      // something logic ...
    }
    ...
  })  // 4. 注入一些組件的選項
  Vue.mixin({    created: function () {      // ...
    }
    ...
  })  // 5. 擴展實例
  Vue.prototype.$ui = {}

}

UIkit中的坑

  當運行以上的代碼後,會很沮喪地發現瀏覽器中總會出現UI.$爲空的異常,具體顯示如下:

Type error UI.$ is undefined.

  我曾嘗試過直接跳入UIkit的源代碼中查找UI.$,這個變量其實是對jQuery的一個內部引用,準確地說這是在引用jQuery的腳本後由jQuery註冊到瀏覽器的window全局變量上的jQuery實例。估計是UIkit在生成加載代碼時變量的映射與初始化順序出現問題了。後來想了個辦法,直接在webpack.config.js配置內對全局變量進行改寫,具體代碼如下:

plugins: [
        new webpack.ProvidePlugin({
            $: "jquery",            jQuery: "jquery",            "window.jQuery": "jquery",            "window.$": "jquery"
        })
]

  webpack.ProvidePlugin這個插件是用於JS代碼加載後在window上註冊全局變量的一個webpack插件,加入了以上的配置後程序就能正常運行了。最終幸運地從大坑中逃出生還!這樣UIkit就被集成到我們的Vue項目中來了。
  本文出自《Vue2實踐揭祕》一書,點此鏈接可在博文視點官網查看此書。
                    圖片描述
  想及時獲得更多精彩文章,可在微信中搜索“博文視點”或者掃描下方二維碼並關注。
                       圖片描述


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章