十分鍾快速上手NutUI


本文將會從 NutUI 初學者的使用入手,對 NutUI 做了一個快速的概述,希望能幫助新人在項目中快速上手。

文章包括以下主要內容

  • 安裝引入 NutUI
  • NutUI 組件的使用
  • NutUI 主題和樣式定制
  • 國際化項目中使用 NutUI

為什么是她

Vue 給大家帶來了組件化,這個功能給開發人員帶來了強大並且簡潔的復用組件能力。設計精美,擴展良好的組件無疑會讓產品效果更加統一,帶來更好的觀看感覺,減少大量重復性工作,提高代碼的可維護性。
當我們最初開始使用一個組件庫的時候,不僅需要從組件庫中簡單地尋找一個能用的組件,而是從產品的角度出發,除了組件庫所提供的基本組件外,尋求她所具備的其他特殊功能。

  • 安裝 & 引入:支持 NPM 方式和 CDN 方式,並支持按需引入
  • 豐富的 feature:豐富的組件,自定義主題,國際化
  • 文檔 & demo:提供友好的文檔和 demo,支持多語言
  • 工程化:開發,測試,構建,部署,持續集成

當然了,最后這個組件庫還應該有持續的更新和維護。我們找了很多組件進行分析測評。先來看一下這一期關於 NutUI 的上手結果。

什么是 NutUI

NutUI 是一款非常優秀的移動端組件庫。50+組件覆蓋,包含基礎類、數據錄入類、操作反饋類、數據展示類、導航類、布局類和業務類組件。而且組件風格統一,開發人員的持續維護,保證了組件的健壯性和可維護性,滿足多數場景M端需求。同時優秀的文檔和活躍的社區支持,給使用者帶來最優的體驗。

img

NutUI 從2017年開始發版,所有組件均是從京東的業務中抽離出來,然后不斷整合修復,最終發展成型。專業的標准設計稿保證一致性,優秀的組件自動化測試和不斷的更新保證組件的穩定性。能夠解決目前市面上多數基於 Vue 開發的 M 端需求,加快使用者開發進度。那么下面我們就帶大家走進 NutUI。

開始上手

我們依據 NutUI 2.2.2 版本的源碼來分析該組件庫的使用和注意事項。當然,NutUI 早期一定不是這樣子的,我們分析的這個版本已經是經過它多次迭代優化后的,如果你想去了解它的發展歷程,可以去 https://github.com/jdf2e/nutui/releases 搜索它的歷史版本。同時,NutUI 也在進行 3.0 版本的開發。 3.0 版本中將會獨立出 Nut-CLI,同時支持 Vue3.0 的語法,全新的組件和規范。期待你的加入。(想要成為 NutUI 的維護者嗎?歡迎去 https://github.com/jdf2e/nutui/issues 中 issue 留言和加入)

img

安裝引入

目前主流的庫都支持 CDN 引入和 NPM 安裝。NutUI 不例外,還更有亮點。

CDN 引入

先說一下 CDN 引入。我們只要在我們的 HTML 頁面上加入如下代碼,就可以完整的使用 NutUI 了。

<!-- 生產環境版本,優化了尺寸和速度 -->
<!-- 引入樣式 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@nutui/nutui/dist/nutui.min.css">
<!-- 引入Vue -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<!-- 引入組件庫 -->
<script src="https://cdn.jsdelivr.net/npm/@nutui/nutui/dist/nutui.min.js"></script>

當然,NutUI 在這方面比較優秀的就是可以 CDN 按需加載引入。 (下面實例為只引入 Button 組件)

 <body>
 <div id="app"><nut-button>CDN按需加載</nut-button></div>

 <!-- 開發環境版本,包含了有幫助的命令行警告 -->
 <!-- 引入樣式 -->
 <link rel="stylesheet"href="https://cdn.jsdelivr.net/npm/@nutui/nutui/dist/packages/button/button.css"/>
 <!-- 引入Vue -->
 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
 <!-- 引入組件庫 -->
 <script src="https://cdn.jsdelivr.net/npm/@nutui/nutui/dist/packages/button/button.js"></script>
 <script>
  Vue.component(button.default.name, button.default);
  new Vue({
     el: "#app"
  });
 </script>
 </body>

注意,CDN 引入使用組件的時候。由於 HTML 中的 attribute 名是大小寫不敏感的,所以瀏覽器會把所有大寫字符解釋為小寫字符。這意味着當你使用 DOM 中的模板時,組件中的 prop 屬性 camelCase (駝峰命名法) 需要使用其等價的 kebab-case (短橫線分隔命名) 命名。詳情參考 Prop用法 ①

NPM 引入

NPM 引入的方式也非常簡潔。我們使用 Vue-CLI 或者 Gaea CLI ② 搭建項目之后。在入口文件添加如下代碼。

Gaea CLI 也是一款 Vue 技術棧單頁面構建工具。且支持一鍵上傳,TypeScript ,Skeleton等特色功能

import Vue from 'vue';
import Nutui from '@nutui/nutui';
import '@nutui/nutui/dist/nutui.css';

Nutui.install(Vue);

當然,如上引入的好處是方便,只需要三行代碼就可以完整地使用 NutUI 所有的組件,但缺點也很明顯,引入的組件包體積很大,通常一個項目也用不到所有的組件,會有資源浪費。

所以最佳方案推薦按需引入。在需要使用某組件的頁面添加如下代碼:(以下為 dialog , picker 組件按需加載)

import Vue from 'vue';
import { Dialog,Picker } from '@nutui/nutui';

Dialog.install(Vue);
Picker.install(Vue);

在這里說明一下,NutUI 會主動打包對應組件的 css 代碼,而不像其他組件庫直接打包所有css。

當我們這樣使用的時候,覺得理所應當,那么為什么 import { Dialog } from '@nutui/nutui'; 可以實現按需引入呢?

實際上我們查看源碼可以得到,NutUI 借助 webpack 的 @nutui/babel-plugin-seperate-import 組件實現將

import { Dialog } from '@nutui/nutui'; 

轉換成如下代碼

import Dialog from '@nutui/nutui/dist/packages/button/button.js'; // 加載構建后的JS
import '@nutui/nutui/dist/packages/button/dialog.css'; //加載構建后的CSS

同時,NutUI 在構建的時候,已經構建出一個完整版的組件庫包和每個組件獨立的包。然后我們手動使用 Dialog.install(Vue) 進行注冊。這樣我們就精准地引入了對應 lib 下的 Dialog 組件的 JS 和 CSS 代碼了。實現了我們的目標:按需加載。

webpack的中如何構建多個bundle呢?主要是entry選項的配置,entry的值通常是一個字符串,其實它還可以是一個對象。我們新增一個webpack配置文件,基於組件庫的組件配置文件生成一個對象,key是組件名,value是組件的入口js文件,將此對象作為該配置文件的entry選項值即可,其他配置與完整版的組件庫webpack配置文件一致(輸出目錄可根據需要自行配置)。構建時執行這兩個配置文件,即可構建出一個完整版的組件庫包和每個組件獨立的包

const cptConf = require('../src/config.json');
const entry = {};
//遍歷所有組件
cptConf.packages.map((item)=>{
    entry[cptName] = `./src/packages/${item.name.toLowerCase()}/index.js`;
});

module.exports = {
    entry
};

組件開箱即用

img

上面我們已經完整的引入了 NutUI,接下來,我們將使用案例來看一下如何使用組件。

使用前准備

我們在使用一個組件庫的時候,最好在 NutUI 官網上提前把該庫所有的組件全部通讀一遍。這樣,不僅使我們對組件庫有一個完整的印象,而且更有利於我們在使用組件的時候具有更多選擇性。比如以下一個案例:

一個 app 開發中,進入項目后,常常會出現一個協議的提示,如圖:

img

大家是不是一下子就想到了使用 Dialog 組件,但是在使用過程中,發現內容過長,而且基礎的 Dialog 不支持內容自定義,更不支持內容的滾動。這個時候是不是束手無策?其實,換種方式,使用 Popup 組件,然后居中展示,內容全部支持自定義,不就完美的解決了我們的需求。所以建議大家在使用前通讀一下所有組件,磨刀不誤砍柴工,反而更加有效的提高開發效率。

漸入佳境

組件了解結束之后,正式進入開發,激動人心的時候終於到了。我們先來看幾個常規的組件。

日歷組件:日歷組件開發過程中常見的剛需組件,一個優秀的日歷組件需要包含能夠選擇日期,區間選擇等功能。

NutUI 的日歷組件的日歷區間選擇功能,支持同一天的選擇。比如選擇2020/05/20-2020/05/20,這可是其他組件不支持的功能哦!

我們使用按需引入的方法來使用日歷組件,在 main.js 中加載日歷組件

import { Calendar } from '@nutui/nutui';
Calendar.install(Vue);

接下來我們在需要的頁面中添加指定組件

<nut-calendar 
 :is-visible.sync="isVisible2"
 :default-value="data2"
 :is-auto-back-fill="true"
 @close="switchPickerClose('isVisible2')"
 @choose="setChooseValue2"
>
</nut-calendar>

<nut-cell :showIcon="true" :isLink="true" @click.native="switchPicker('isVisible2')">
     <span slot="title"><label>日期選擇</label></span>
     <span slot="sub-title">有默認日期,選擇后自動回填的~~~</span>
     <div slot="desc" class="selected-option" >
       <span class="show-value">{{date2 ? date2 : '請選擇日期'}}</span>
     </div>
 </nut-cell>

// js部分
export default {
 data() {
   return {
     isVisible2: false,
     date2: '2020-12-22',
   };
 },
 methods: {
   setChooseValue2(param) {
     this.date2 = param[3];
   },
   switchPickerClose(isVisible2){
    this.isVisible2=!this.isVisible2;
   }
 }
};

上面代碼中,is-visible.sync 是來控制日歷是否展示,default-value 是展示日歷的默認日期,close 是關閉事件,choose是我們選擇日期的事件觸發。默認日歷組件時不顯示的,我們需要通過點擊 Cell 來控制日歷組件,這樣一個完整的日歷效果就實現了,剩下的就是我們處理自己的業務了!

思考 : 為什么要使用 .sync ?

除了日歷組件這種需要在頁面上放置組件來展示的,部分組件支持直接函數式調用,比如 Dialog組件,我們來體驗一下。

先全局注冊 Dialog 組件。

import { Button , Dialog } from '@nutui/nutui';
Button.install(Vue);
Dialog.install(Vue);

然后我們在按鈕上添加一個事件,在事件中使用dialog

<nut-button 
 @click="clickHandler"
>
 提交
</nut-button>

//js部分
export default {
 data() {},
 methods: {
   clickHandler() {
     this.$dialog({
       title: "提交",
       content: "你確定提交當前數據嗎",
       closeBtn:true, //顯式右上角關閉按鈕
       onOkBtn(event) { //確定按鈕點擊事件
        alert("okBtn");
        this.close(); //關閉對話框
       },
       onCancelBtn(event) { //取消按鈕點擊事件,默認行為關閉對話框
        alert("cancelBtn");
        //return false; //阻止默認“關閉對話框”的行為
       },
       onCloseBtn(event) { //右上角關閉按鈕點擊事件
        alert("closeBtn");
        //return false; //阻止默認“關閉對話框”的行為
       },
       closeCallback(target) {
        alert("had close"); //對話框關閉回調函數,無論通過何種方式關閉都會觸發
       }
    });
   }
 }
};

Image text

dialog 的內容不僅支持文字,同時支持圖片類型。

this.$dialog({
 type:"image", //設置彈窗類型為”圖片彈窗“
 link:"http://m.jd.com", //點擊圖片跳轉的Url
 imgSrc:"m.360buyimg.com//5b9549eeE4997a18c/070eaf5bddf26be8.jpg", //圖片Url
 onClickImageLink:function(){ 
    //圖片點擊事件,默認行為是跳轉Url
    console.log(this);
    //返回false可阻止默認的鏈接跳轉行為
 }
});

Image text

為什么我們使用 Dialog 可以直接通過 this 來直接調用呢?原因就是 Dialog 組件在構建的時候,其實構建了兩種:一種支持我們使用組件式使用,另一種支持我們使用函數式調用。

import DialogVue from './dialog.vue';
import Dialog from './_dialog';
import './dialog.scss';

const DialogArr = [Dialog, DialogVue];

DialogArr.install = function(Vue){
Vue.prototype['$dialog'] = Dialog;
Vue.component(DialogVue.name, DialogVue);
}

上面代碼我們可以看到,Dialog 構建時,不僅使用了 Vue.prototype 來擴展一個新的方法,同時也使用了 Vue.component 來實現組件式調用。

額外驚喜

NutUI 中目前不僅有傳統的通用組件,現在也在逐漸增加好多特色組件。比如目前已經有的抽獎組件和簽名組件。先去官網一睹為快吧!

Image textImage text

(更多組件和使用方法參考官網文檔 https://nutui.jd.com/)

主題定制

使用任何一個組件功能可以類似,但樣式卻是各式各樣。如何在使用 NutUI 的基礎上實現自己的樣式定制呢?

全局定制

首先我們來看,NutUI 中所有公共的樣式都在 dist\styles\variable.scss 中。當我們想要修改的時候,可以在項目中創建一個 scss 文件,然后復制公共樣式中所有變量。

我們需要修改一下配置。在vue.config.js 的 css 配置或者 webpack 中的 sass-loader 的配置。引入我們自定義的 scss 文件,注意屬性哦。

module.exports = {
 css: {
   loaderOptions: {
     // 給 sass-loader 傳遞選項
     scss: {
       // @/ 是 src/ 的別名
       // 注意:在 sass-loader v7 中,這個選項名是 "data"
       prependData: ` 
       @import "@/assets/custom_theme.scss"; //這個是我們自定義的scss文件@import "@nutui/nutui/dist/styles/index.scss";
       `,
     }
   },
 }
}

然后我們使用組件的時候,需要引入 SCSS 文件,而不是 CSS 文件。這樣變完成了對 NutUI 的全局樣式定制。

import Nutui from '@nutui/nutui';
import '@nutui/nutui/dist/nutui.scss';

私人定制

當然,如果我們項目中某個特殊組件需要修改樣式,而且不想影響該組件在其他地方的使用,我們可以在頁面上直接使用 /deep/ 進行樣式修改,但是注意添加對樣式style 添加 scoped 哦!

/deep/ 是Vue提供的深度選擇器。詳情參考 VUE官網 Scope CSS ③

國際化

隨着越來越多的多語言項目進入我們的開發需求中。國際化方案成為一種必需品。談到 Vue 的國際化方案,大家很容易會聯想到 vue-i18n 方案,NutUI 並未引入 vue-i18n,不過它是可以很好地兼容 vue-i18n 。

NutUI 的國際化

所有的國際化方案都會用到語言包,語言包通常會返回一個 JSON 格式的數據,NutUI 組件庫的語言包在 locale/lang 目錄下。我們使用的時候,需要在引入 NutUI 的時候同時引入對應的語言包。如下是引用了英語語言包。

import Vue from 'vue';
import NutUI from '@nutui/nutui';
import enUS from '@nutui/nutui/dist/locales/lang/en-US';

Vue.use(NutUI , {
 locale: 'en-US',
 lang: enUS
});

這樣我們的頁面中所有關於 NutUI 組件的都會使用英語語言展示,如圖:

Image text

整個項目的國際化

當然,這只是修改了組件內部的語言,如何將 NutUI 和自己的語言包完美融合呢?我們構建一個自己的語言包。

// zh_cn.js文件
export default {
 app: {
   hello: '你好,世界!'
 }
}

// en_us.js文件
export default {
 app: {
   hello: 'Hello,World!'
 }
}

然后再入口文件中進行引入。

import Vue from 'vue';
import VueI18n from 'vue-i18n';
import {locale} from '@nutui/nutui';
import enUS from '@nutui/nutui/dist/locales/lang/en-US';
import zhCN from '@nutui/nutui/dist/locales/lang/zn-CH';
import enLocale from './en_us';
import zhLocale from './zh_cn';

Vue.use(VueI18n);
Vue.locale = () => {};
// 將語言包進行合並
const messages = {
 en: {
 ...enUS,
 ...enLocale
 },
 zh: {
 ...zhCN,
 ...zhLocale
 }
}

const i18n = new VueI18n({
 locale: 'zh', // 設置默認語言
 messages: messages // 設置資源文件對象
})
//
const app = new Vue({
 el: '#app',
 i18n
})

這樣便將 i18n 和我們 NutUI 的語言包進行了合並。如何在頁面中使用呢?

<template>
  <nut-navbar :title="$t('app.hello')" @click-left="show=true">
  </nut-navbar>
</template>

我們在 JS 中使用的時候需要加上 this。例如:

created () {
 console.log('start to enter created ', this.$t('app.hello'))
}

接下來,我們在語言切換的按鈕上綁定如下事件,即可完美的實現語言切換功能了。

tabEn: function () { 
 this.$i18n.locale = 'en' 
}, 
tabCn: function () { 
 this.$i18n.locale = 'zh' 
}

這樣,我們就完美的實現了多語言的展示和切換功能。是不是很優秀?

文檔 & Demo

當我們使用一個組件庫的時候,友好的文檔和 Demo 是必不可少的。她可以讓我們更方便快捷的使用。NutUI 的 Demo 和文檔是分開的。從 NutUI 的Github ④中可以看出,NutUI 把所有的組件都放在 src/packages 下面。每一個組件大概由下面幾部分組成。

img

其中_test 文件夾內是組件的單元測試。NutUI 如何進行單元測試可參考文章 NutUI單元測試實踐 ⑤。其中詳細介紹了如何編寫單元測試和在 NutUI 中單元測試實踐。

剩下的文件中以組件命名的 js ,vue , css 文件,是該組件的核心。上面也介紹了一個組件是如何從0開始構建的,一個通用的組件從參數傳入,參數處理,校驗,參數存儲,function 回調等各種特性保證才產出。

demo.vue 文件包含了該組件各種常規用法。我們官網上所有的實例寫法,都可以在對應組件的 demo 文件種找到。同學們可以如果有需求,可以只看 demo ,來 copy 你想要的功能哦!

最后我們說到的是.md 文件。md 文件就是我們官網上對該組件的說明和使用方法,我們是如何將 md 直接變成我們的官網呢,NutUI官網構建的關鍵技術揭秘 ⑥可以得到答案哦!

結束語

至此,關於NutUI 的基本使用,我們今天就先介紹到這里。是不是很心動,趕快在你的項目中使用起來吧!同時 https://github.com/jdf2e/nutui/issues 歡迎你的建議。本文中所有的示例都收錄在https://github.com/jdf2e/nutui-demo 歡迎訪問點贊!!

參考連接

①  Vue關於prop用法  https://cn.vuejs.org/v2/guide/components-props.html
②  Gaea CLI  https://github.com/jdf2e/Gaea4
③  VUE官網 Scope CSS  https://vue-loader.vuejs.org/zh/guide/scoped-css.html#混用本地和全局樣式
④  NutUI 的Github地址 https://github.com/jdf2e/nutui
⑤  NutUI單元測試實踐  https://juejin.im/post/5e66ee55f265da57133b3927
⑥  NutUI官網構建的關鍵技術揭秘 https://juejin.im/post/5ebb4a686fb9a0437055c33d


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM