使用Labrador 0.3構建ES6/ES7標準模塊化微信小程序

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

因此最佳的姿式是:

  1. 在項目中運行 labrador watch

  2. 在WebStorm中編碼,保存

  3. 切換到 微信web開發者工具 中調試、預覽

  4. 再回到WebStorm中編碼

  5. ...

labrador 庫

labrador 庫對全局的 wx 變量進行了封裝,將大部分 wx 對象中的方法進行了Promise支持, 除了以 on* 開頭或以 *Sync 結尾的方法。在以下代碼中使用 labrador 庫。

import wx from 'labrador';

咱們建議不要再使用 wx.getStorageSync() 等同步阻塞方法,而在 async 函數中使用 await wx.getStorage() 異步非阻塞方法提升性能,除非特殊狀況。

app.js

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 分別對應微信小程序框架的 jswxmlwxss 文件。在Labardor項目源碼中,咱們特地採用了 xmlless 後綴以示區別。

自定義組件示例

下面是一個簡單的自定義組件代碼實例:

邏輯 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 ,這個屬性定義了該組件依賴、包含的其餘自定義組件,在上面的代碼中頁面包含了兩個自定義組件 listtitle ,這個兩個自定義組件的 key 分別爲 listmotto

xml佈局代碼中,使用了Labrador提供的 <component/> 標籤,此標籤的做用是導入一個自定義子組件的佈局文件,標籤有兩個屬性,分別爲 key (必選)和 name (可選,默認爲key的值)。key 與js邏輯代碼中的組件 key 對應,name 用來在src/componetsnode_modules 目錄中尋找子組件模板。運行時,key對應的子組件邏輯代碼類中的 data 將渲染至子組件模板中。

less樣式文件中,咱們使用了兩條 @import 語句加載子組件樣式,這裏的 @import 'list' 語句按照LESS的語法,會首先尋找當前目錄 src/pages/index/ 中的 list.less 文件,若是找不到就會嘗試尋找 src/componetsnode_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 包含子組件 listtitlelist 包含子組件 title,因此在最終顯示時,index 頁面上回顯示兩個 title 組件。

詳細代碼請參閱 labrador init 命令生成的示例項目。

總結

頁面也是組件,全部的組件都擁有同樣的生命週期函數onLoad, onReady, onShow, onHide, onUnload 以及setData函數。

componetspages 兩個目錄的區別在於,componets 中存放的組件可以被智能加載,pages 目錄中的組件在編譯時自動加上 Page() 調用,因此,pages 目錄中的組件不能被其餘組件調用,若是某個組件須要重用,請存放在 componets 目錄或打包成NPM包。

貢獻者

鄭州脈衝軟件科技有限公司

梁興臣

開源協議

本項目依據MIT開源協議發佈,容許任何組織和我的無償使用。

相關文章
相關標籤/搜索