Labrador 是一個專爲微信小程序開發的模塊化的前端開發框架css
在微信小程序開發三宗罪和解決方案一文中我向你們闡述了微信小程序開發的三個弊端,並提供了Labrador框架來解決這些弊端。前端
在上一個版本的Labrador中,組件重用部分功能不完善,今天Labrador發佈了0.3版本,相對上一個版本,提供了更強大的組件化功能,並更改了一些模塊接口。node
下面是Labrador 0.3.x版本的入門手冊,若是你已經基於老版本Labrador構建了項目,請參照下面的說明對應升級項目,並升級一下全局的 labrador-cli 庫到0.3版本。git
QQ交流羣 282140496github
使用Labrador框架可使微信開發者工具支持加載海量NPM包web
支持ES6/ES7標準代碼,使用async/await可以有效避免回調地獄npm
組件重用,對微信小程序框架進行了二次封裝,實現了組件重用和嵌套json
使用Editor Config及ESLint標準化代碼風格,方便團隊協做小程序
npm install -g labrador-cli
mkdir demo cd demo npm init labrador init
demo # 項目根目錄 ├── .babelrc # babel配置文件 ├── .editorconfig # Editor Config ├── .eslintignore # ESLint 忽略配置 ├── .eslintrc # ESLint 語法檢查配置 ├── package.json ├── dist/ # 目標目錄 ├── node_modules/ └── src/ # 源碼目錄 ├── app.js ├── app.json ├── app.less ├── components/ # 通用組件目錄 ├── pages/ # 頁面目錄 └── utils/
注意 dist目錄中的全部文件是由labrador命令生成,請勿直接修改segmentfault
項目初始化後使用WebStorm或Sublime等你習慣的IDE打開項目根目錄。而後打開 微信web開發者工具 新建項目,本地開發目錄選擇 dist
目標目錄。
在WebStorm或Sublime等IDE中編輯 src
目錄下的源碼,而後在項目根目錄中運行labrador build
命令構建項目,而後在 微信web開發者工具 的調試界面中點擊左側菜單的 重啓 按鈕便可查看效果。
咱們在開發中, 微信web開發者工具 僅僅用來作調試和預覽,不要在 微信web開發者工具 的編輯界面修改代碼。
微信web開發者工具 會偶爾出錯,表現爲點擊 重啓 按鈕沒有反應,調試控制檯輸出大量的沒法require文件的錯誤,編輯 界面中代碼文件不顯示。這是由於
labrador build
命令會更新整個dist
目錄,而 微信web開發者工具 在監測代碼改變時會出現異常,遇到這種狀況只須要關掉 微信web開發者工具 再啓動便可。
咱們還可使用 labrador watch
命令來監控 src
目錄下的代碼,當發生改變後自動構建,不用每一次編輯代碼後手動運行 labrador build
。
因此最佳的姿式是:
在項目中運行 labrador watch
在WebStorm中編碼,保存
切換到 微信web開發者工具 中調試、預覽
再回到WebStorm中編碼
...
labrador
庫對全局的 wx
變量進行了封裝,將大部分 wx
對象中的方法進行了Promise支持, 除了以 on*
開頭或以 *Sync
結尾的方法。在以下代碼中使用 labrador
庫。
import wx from 'labrador';
咱們建議不要再使用 wx.getStorageSync()
等同步阻塞方法,而在 async
函數中使用 await wx.getStorage()
異步非阻塞方法提升性能,除非特殊狀況。
src/app.js
示例代碼以下:
import wx from 'labrador'; import { sleep } from './utils/util'; export default class { globalData = { userInfo: null }; async onLaunch() { //調用API從本地緩存中獲取數據 let logs = await wx.getStorage({ key: 'logs' }) || []; logs.unshift(Date.now()); await wx.setStorage({ key: 'logs', data: logs }); this.timer(); } async timer() { while (true) { console.log('hello'); await sleep(10000); } } async getUserInfo() { if (this.globalData.userInfo) { return this.globalData.userInfo; } await wx.login(); let res = await wx.getUserInfo(); this.globalData.userInfo = res.userInfo; return res.userInfo; } }
代碼中所有使用ES6/ES7標準語法。代碼沒必要聲明 use strict
,由於在編譯時,全部代碼都會強制使用嚴格模式。
代碼中並未調用全局的 App()
方法,而是使用 export
語法默認導出了一個類,在編譯後,Labrador會自動增長 App()
方法調用,全部請勿手動調用 App()
方法。
Labrador的自定義組件,是基於微信小程序框架的組件之上,進一步自定義組合,擁有邏輯處理和樣式。這樣作的目的請參見 微信小程序開發三宗罪和解決方案
項目中通用自定義組件存放在 src/compontents
目錄,一個組件通常由三個文件組成,*.js
、 *.xml
和 *.less
分別對應微信小程序框架的 js
、 wxml
和 wxss
文件。在Labardor項目源碼中,咱們特地採用了 xml
和 less
後綴以示區別。
下面是一個簡單的自定義組件代碼實例:
邏輯 src/compontents/title/title.js
import wx from 'labrador'; import randomColor from '../../utils/random-color'; export default class Title extends wx.Component { data = { text: '', color: randomColor() }; handleTap() { this.setData({ color: randomColor() }); } }
佈局 src/compontents/title/title.js
<view class="text-view"> <text class="title-text" catchtap="handleTap" style="color:{{color}};">{{text}}</text> </view>
樣式 src/compontents/title/title.less
.title-text { font-weight: bold; font-size: 2em; }
代碼和微信小程序框架中的page很類似。最大的區別是在js邏輯代碼中,沒有調用全局的Page()
函數聲明頁面,而是用 export
語法導出了一個默認的類,這個類須要繼承與 labrador.Component
組件基類。
注意 組件中事件響應方法必須以
handle
開頭!例如上文中的handleTap
咱們要求全部的頁面必須存放在 pages
目錄中,每一個頁面的子目錄中的文件格式和自定義組件一致,只是能夠多出一個 *.json
配置文件。
下面是默認首頁的示例代碼:
邏輯 src/pages/index/index.js
import wx from 'labrador'; import List from '../../components/list/list'; import Title from '../../components/title/title'; export default class Index extends wx.Component { data = { userInfo: {} }; children = { list: new List(), motto: new Title({ text: 'Hello world' }) }; //事件處理函數 handleViewTap() { wx.navigateTo({ url: '../logs/logs' }) } async onLoad() { //調用應用實例的方法獲取全局數據 let userInfo = await wx.app.getUserInfo(); //更新數據 this.setData({ userInfo: userInfo }); this.update(); } }
佈局 src/pages/index/index.xml
<view class="container"> <view bindtap="handleViewTap" class="userinfo"> <image class="userinfo-avatar" src="{{ userInfo.avatarUrl }}" background-size="cover"/> <text class="userinfo-nickname">{{ userInfo.nickName }}</text> </view> <view class="usermotto"> <component key="motto" name="title"/> </view> <component key="list"/> </view>
樣式
@import 'list'; @import 'title'; .motto-title-text { font-size: 3em; padding-bottom: 1rem; } /* ... */
頁面代碼的格式和自定義組件的格式如出一轍,咱們的思想是 頁面也是組件,頁面和自定義組件的惟一差異是頁面的代碼存放在 pages
目錄中。
js邏輯代碼中一樣使用 export
語句導出了一個默認類,也不能手動調用 Page()
方法,由於在編譯後,pages
目錄下的全部js文件所有會自動調用 Page()
方法聲明頁面。
咱們看到組件類中,有一個對象屬性 children
,這個屬性定義了該組件依賴、包含的其餘自定義組件,在上面的代碼中頁面包含了兩個自定義組件 list
和 title
,這個兩個自定義組件的 key
分別爲 list
和 motto
。
xml佈局代碼中,使用了Labrador提供的 <component/>
標籤,此標籤的做用是導入一個自定義子組件的佈局文件,標籤有兩個屬性,分別爲 key
(必選)和 name
(可選,默認爲key的值)。key
與js邏輯代碼中的組件 key
對應,name
用來在src/componets
和 node_modules
目錄中尋找子組件模板。運行時,key對應的子組件邏輯代碼類中的 data
將渲染至子組件模板中。
less樣式文件中,咱們使用了兩條 @import
語句加載子組件樣式,這裏的 @import 'list'
語句按照LESS的語法,會首先尋找當前目錄 src/pages/index/
中的 list.less
文件,若是找不到就會嘗試尋找 src/componets
和 node_modules
目錄中的組件樣式。
接下來,咱們定義了 .motto-title-text
樣式,這樣作是由於 motto
key 表明的title組件的模板中有一個view 屬於 title-text
類,編譯時,Labrador將自動爲其增長一個前綴 motto-
,因此編譯後這個view所屬的類爲 title-text motto-title-text
那麼咱們就能夠在父組件的樣式代碼中使用 .motto-title-text
從新定義子組件的樣式。
注意 雖然咱們採用了LESS文件,可是因爲微信小程序框架的限制,不能使用LESS的層級選擇及嵌套語法。可是咱們可使用LESS的變量、mixin、函數等功能方便開發。
另外Labrador支持多層組件嵌套,在上述的實例中,index
包含子組件 list
和 title
,list
包含子組件 title
,因此在最終顯示時,index
頁面上回顯示兩個 title
組件。
詳細代碼請參閱 labrador init
命令生成的示例項目。
頁面也是組件,全部的組件都擁有同樣的生命週期函數onLoad, onReady, onShow, onHide, onUnload 以及setData函數。
componets
和 pages
兩個目錄的區別在於,componets
中存放的組件可以被智能加載,pages
目錄中的組件在編譯時自動加上 Page()
調用,因此,pages
目錄中的組件不能被其餘組件調用,若是某個組件須要重用,請存放在 componets
目錄或打包成NPM包。
本項目依據MIT開源協議發佈,容許任何組織和我的無償使用。