小程式從入門到實戰系列(一)

viewer_w發表於2018-08-31

前言

隨著小程式日漸火熱,扇貝在近一年投入了大量的精力來做小程式的相關業務,小程式相比於 APP 更容易傳播,因為小程式是基於強大的社交平臺微信的基礎上的,這使其具有極強的傳播能力,甚至可以在微信朋友圈產生病毒性傳播,一夜爆紅。

在看到頭腦王者小程式幾乎一夜爆紅之後,其日活最好時期達到了百萬級別,我們開始著手開發了單詞大師,之前沒有任何小程式的開發經驗,幾乎是零基礎,然後就開始了小程式的採坑之路。在單詞大師的功能迭代完成後,我們又開發了另一個小程式扇貝每日英語,接下來我會主要跟大家分享在這兩個小程式的開發過程中遇到一些問題以及解決的辦法。因為準備寫一個小的系列文章,所以會從小程式的入門進行講解,後面逐步深入,最後會有一個開源個人專案的實戰講解,敬請期待。

準備工作

在此,我們預設讀者具有一定的前端開發經驗,掌握 css、html、javascript、以及熟悉流行的 MVVM 框架,熟悉打包構建工具。

微信官方提供了小程式的開發文件,你可以點選這裡前往檢視小程式的官方文件,首先,你需要按照指引,建立一個微信小程式賬號,然後登陸公眾平臺可以看到你的 appId,然後下載微信開發者工具,就可以預覽一個微信官方提供的小 demo 了,然後需要用一個下午或者更多的時間去看一遍小程式文件中的框架、元件、API。

至此,你應該可以通過讀文件完成以下任務:

  1. 可以讀懂 demo 的程式碼了。
  2. 熟悉小程式的框架、配置、頁面的生命週期事件、小程式資料繫結機制(邏輯層與檢視層的互動、setDate)。
  3. 熟悉常用元件的使用:view、image、scroll-view、swiper、button、form、textarea、navigater、canvas 等等。
  4. 熟悉所有的 api,特別是介面方面的 api 要先比較熟悉。

如果你還沒有讀完一遍微信的官方文件,我建議你先別往下看了,找個時間熟悉了小程式的官方文件中的框架、元件、api 後,再繼續往下瀏覽吧。

如果看完了文件,對於 demo 的程式碼還不是很懂,那我簡單帶你看一下 demo 的程式碼吧。

demo 原始碼分析

首先看程式碼的結構:

├── app.js
├── app.json
├── app.wxss
├── pages
│   ├── index
│   │   ├── index.js
│   │   ├── index.wxml
│   │   └── index.wxss
│   └── logs
│       ├── logs.js
│       ├── logs.json
│       ├── logs.wxml
│       └── logs.wxss
├── project.config.json
└── utils
    └── util.js
複製程式碼

這個 demo 的程式碼結果很簡單清晰,我們主要看三個部分:

專案配置檔案 project.config.json

這個檔案記錄了你的小程式專案在在開發者工具上的一些配置資訊,具體配置參考配置,比如:專案名稱,小程式 appid,基礎庫版本,開發者工具的專案設定,如果你使用了小程式的雲服務,就需要在這裡面配置小程式的 miniprogramRoot 和 qcloudRoot,如果專案有一些自定義的編譯條件,這邊編譯資訊也會被記錄到condition:miniprogram 下面。

小程式的全域性 app

app 就是描述小程式整體的一個容器,它會先於頁面被初始化,它主要由三個檔案構成:app.js、app.json、app.wxss。demo 程式碼裡面 app.js 使用到了 app 生命週期函式 onLaunch,和全域性資料容器 globalData。小程式初始化的時候會觸發 app 的 onLaunch 事件,這個方法也會先於 page 的 onLoad 事件被執行。因此,我們可以在 onLaunch 方法裡面執行一些小程式初始化時需要完成的事情,比如 demo 裡面做的事情:獲取使用者資訊。

因為每個 page 有屬於自己獨立的 data,如果我們需要維護一些多個頁面共享的資料,這時候就可以使用 globalData,當然你也可以使用一些資料管理的庫,比如 redux,vuex.最新的小程式原生開發已經支援 npm 了。這使得引入依賴庫變得很方便了。

app.json 檔案用來對微信小程式進行全域性配置,決定頁面檔案的路徑、視窗表現、設定網路超時時間、設定多 tab 等,具體檢視配置

小程式頁面 page

小程式的每個頁面最多由四個檔案構成:page.js、page.wxml、page.json、page.wxss。

js 檔案用來寫頁面邏輯,wxml 檔案類似 html,是小程式的模板檔案,json 檔案是頁面的配置檔案,wxss 是頁面的樣式檔案,類似 css 檔案。

//index.js
//獲取應用例項
const app = getApp();

Page({
    data: {
        motto: 'Hello World',
        userInfo: {},
        hasUserInfo: false,
        canIUse: wx.canIUse('button.open-type.getUserInfo'),
    },
    //事件處理函式
    bindViewTap: function() {
        wx.navigateTo({
            url: '../logs/logs',
        });
    },
    onLoad: function() {
        if (app.globalData.userInfo) {
            this.setData({
                userInfo: app.globalData.userInfo,
                hasUserInfo: true,
            });
        } else if (this.data.canIUse) {
            // 由於 getUserInfo 是網路請求,可能會在 Page.onLoad 之後才返回
            // 所以此處加入 callback 以防止這種情況
            app.userInfoReadyCallback = res => {
                this.setData({
                    userInfo: res.userInfo,
                    hasUserInfo: true,
                });
            };
        } else {
            // 在沒有 open-type=getUserInfo 版本的相容處理
            wx.getUserInfo({
                success: res => {
                    app.globalData.userInfo = res.userInfo;
                    this.setData({
                        userInfo: res.userInfo,
                        hasUserInfo: true,
                    });
                },
            });
        }
    },
    getUserInfo: function(e) {
        console.log(e);
        app.globalData.userInfo = e.detail.userInfo;
        this.setData({
            userInfo: e.detail.userInfo,
            hasUserInfo: true,
        });
    },
});
複製程式碼

我們分析一下 index.js 的程式碼,通過 getAPP(),獲取全域性 app 物件,從而可以呼叫 app 裡面的方法,使用 globalData 裡的全域性資料。data 裡放著頁面的內部資料,通過 setData()去改變資料,從而改變檢視。這與 MVVM 框架的設計是一致的。與檢視無關的頁面資料不要放在 data 裡面,因為邏輯層和渲染層傳輸資料(經 JSON.stringify 序列化為字串)的是比較佔用程式資源的。onLoad 是頁面的初始化生命週期函式,我們在這個函式裡初始化頁面資料。另外 page 裡剩下的是頁面的點選事件和自定義函式。

再來看看 index.js 中使用到的 api,首先wx.canIUse用來判斷小程式的 API,回撥,引數,元件等是否在當前版本可用。因為小程式的基礎庫隨著微信客戶端版本升級,如果有些使用者沒有升級微信客戶端,那麼一些新的 api、元件特性就無法使用,這時候我們可以使用 canIUse 做相容處理。wx.getUserInfo,這個介面使用者獲取使用者的資訊,如果使用者未授權過,呼叫該介面將直接進入 fail 回撥,更詳細的入參、返回值、使用場景請檢視文件。wx.navigateTo保留當前頁面,跳轉到應用內的某個頁面,使用 wx.navigateBack 可以返回到原頁面。這兒涉及到小程式的頁面路由,小程式的頁面間有哪幾種路由跳轉方式,此時的頁面棧是什麼樣的,以及分別觸發了兩個頁面的那些生命週期,具體參加路由文件

demo 中 index 頁面並沒有配置 index.json 檔案,頁面的配置只能設定 app.json 中部分 window 配置項的內容,頁面中配置項會覆蓋 app.json 的 window 中相同的配置項。具體參見配置

小程式框架選擇

由於小程式的原生開發存在太多的不方便:不支援 npm(現已經支援),蹩腳的模板語法、檔案過於分散、request 併發問題、api 非 promise、缺少配套的狀態管理庫。 我們最先接觸的是wepy 框架,這個框架解決了大部分原生開發存在的問題,採用類 Vue.js 的語法,減小開發小程式的語法學習成本,支援元件化,支援 npm,支援 promise,支援一些通用的 css、js 編譯器和圖片壓縮外掛。所以,我們的單詞大師小程式就使用了 wepy 框架。

但是很快美團的mpvue 框架橫空出世,它給我們帶來了什麼呢?

  • 徹底的元件化開發能力:提高程式碼複用性
  • 完整的 Vue.js 開發體驗
  • 方便的 Vuex 資料管理方案:方便構建複雜應用
  • 快捷的 webpack 構建機制:自定義構建策略、開發階段 hotReload
  • 支援使用 npm 外部依賴
  • 使用 Vue.js 命令列工具 vue-cli 快速初始化專案
  • H5 程式碼轉換編譯成小程式目的碼的能力

是不是很驚喜,是不是很震撼?這完全就是 Vue 開發 web 應用的那一套啊,對於熟悉 Vue 的開發者來說基本就是零學習成本開發微信小程式。mpvue 相比於 wepy 的優勢立馬顯現出來,首先,mpvue 擁有完整的 vue 語法規範(雖然小部分語法不能用),配套的資料管理 Vuex,整合 webpack 打包構建工具(wepy 使用自己的一個打包構建工具,顯然沒有 webpack 強大),還有方便 h5 和小程式複用專案程式碼。

最後在對比一下兩個框架:

mpvue wepy
語法 vuejs 類 vuejs
標籤 html+小程式 小程式
元件化 Vue 規範 自定義元件規範
自動構建 webpack 框架內建
學習成本 vue+小程式 vue+wepy+小程式
資料管理 vuex redux

wepy 專案建立和使用

安裝最新的 wepy-cli,並使用標準的模板初始化專案:

npm install -g wepy-cli
wepy init standard myproject
複製程式碼

初始化專案會需要你在終端輸入專案名稱,小程式 appid,描述,是否啟用 redux,是否使用 eslint.

使用wepy list可以列出可以選擇的其他初始化專案模板。

切換至專案目錄

cd myproject
複製程式碼

安裝依賴

npm install
複製程式碼

開啟實時編譯

npm run dev
複製程式碼

wepy 專案的目錄結構

.
├── package.json
├── project.config.json
├── src
│   ├── app.wpy
│   ├── components
│   │   ├── counter.wpy
│   │   ├── group.wpy
│   │   ├── groupitem.wpy
│   │   ├── list.wpy
│   │   ├── panel.wpy
│   │   └── wepy-list.wpy
│   ├── index.template.html
│   ├── mixins
│   │   └── test.js
│   ├── pages
│   │   └── index.wpy
│   └── store
│       ├── actions
│       │   ├── counter.js
│       │   └── index.js
│       ├── index.js
│       ├── reducers
│       │   ├── counter.js
│       │   └── index.js
│       └── types
│           ├── counter.js
│           └── index.js
└── wepy.config.js
複製程式碼

為了方便我們開發,我們還要在模板的基礎上改造一下。因為產品開發至少會有一個開發環境,一個生產環境,所以,我們可以新建一個 config 目錄,新增兩個環境的配置檔案。

首先 package.json 中指定 NODE_ENV 環境變數值:

 "scripts": {
        "start": "cross-env NODE_ENV=local npm run dev",
        "preview": "cross-env NODE_ENV=preview wepy build --no-cache",
        "dev": "wepy build --watch",
        "build": "cross-env NODE_ENV=production wepy build --no-cache",
        "clean": "find ./dist -maxdepth 1 -not -name 'project.config.json' -not -name 'dist' | xargs rm -rf",
        "test": "echo \"Error: no test specified\" && exit 1"
    },
複製程式碼

然後在 wepy.config.js 中配置 resolve:alias:

const env = process.env.NODE_ENV || 'production';
//
module.exports = {
 resolve: {
        alias: {
            ... //other alias
            '@config': path.join(__dirname, `src/config/config.${env}.js`),
        },
        modules: ['node_modules'],
    },
}
複製程式碼

這樣你 import * from '@config',就會根據當前的環境載入不同的 config 了。

詳細指引參考wepy 官方文件;

mpvue 框架使用

直接檢視官方文件吧。

小結

框架選擇好了以後,我們就開始準備開發自己的小程式吧。

下篇我們一起學習如何利用騰訊雲+mpvue 開發一個自己的小程式---拼詞樂鬥。線上預覽:

小程式從入門到實戰系列(一)
小程式從入門到實戰系列(一)

相關文章