現學現賣微信小程式開發(一)

接灰的電子產品發表於2016-12-30

現學現賣微信小程式開發(二)
現學現賣微信小程式開發(三):引入Rx,為小程式插上翅膀

很早就註冊了微信小程式內測,因為是拖延症晚期患者,所以一直都沒有學習。直到昨天(2016年12月28日),張小龍童鞋宣佈微信小程式2017年1月9日正式上線,滿屏都是小程式的訊息。我這時才想起來,我不能白交了300塊錢啊,得學啊。

反正學習也得總結,倒不如現學現賣寫一個教程吧。話說回來現學現賣肯定有不少錯誤,大家多包涵哈。廢話少說,我們開工,首先下載微信小程式開發工具 mp.weixin.qq.com/debug/wxado… 選擇自己的平臺下載安裝即可。

現學現賣微信小程式開發(一)
微信小程式開發工具下載頁面

註冊小程式號的過程我就不講了(網上這類教程一堆,不用我花時間在這裡。),你要開發的話,最好通過公司申請一個。第一次啟動開發工具時需要掃碼,然後選擇新增一個無appId的專案。做個什麼專案好呢,沒想好,那就還是先把Todo牽出來吧。我們來實現一個微信小程式版的Todo,同樣是帶HTTP後臺的版本。為什麼又選擇Todo呢?因為它的邏輯相對完整,增刪改查都有,HTTP請求、返回俱全。在一個平臺折騰明白這個app就基本可以上手幹活了,這貨簡直就是新時代的Hello World啊。

檔案結構

新建工程時,預設開發工具會生成一個樣例給我們。我們就來看看這個樣例是什麼東東。開發工具的左側是一個預覽,中間那欄是檔案目錄,看目錄結構倒是蠻簡單:

現學現賣微信小程式開發(一)
開發工具自動幫助生成了一個樣本工程

全域性檔案

先來看一下根目錄:這個目錄下有三個檔案app.js,app.json和app.wxss。app.js是應用入口,裡面定義了App() 函式,用來註冊一個小程式,就像Android裡面的Application和Angular2中的。接受一個 object 引數,其指定小程式的生命週期函式等。

//app.js
App({
  onLaunch: function () {
    //呼叫API從本地快取中獲取資料
    var logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)
  },
  getUserInfo:function(cb){
    var that = this
    if(this.globalData.userInfo){
      typeof cb == "function" && cb(this.globalData.userInfo)
    }else{
      //呼叫登入介面
      wx.login({
        success: function () {
          wx.getUserInfo({
            success: function (res) {
              that.globalData.userInfo = res.userInfo
              typeof cb == "function" && cb(that.globalData.userInfo)
            }
          })
        }
      })
    }
  },
  globalData:{
    userInfo:null
  }
})複製程式碼

從上面的例子程式碼看的話,雖然簡單還是能看出一些東西的:

  • App()本身就是一個函式,在其他頁面可以通過系統提供的getApp()來得到應用的例項。
  • onLaunch就是一個生命週期函式,是當小程式初始化完成時,會觸發這個函式(只觸發一次)。這裡在應用初始化時向本地儲存寫入了一個日期。
  • globalData是個全域性資料的存放區域,示例程式碼中只放置了一個userInfo作為全域性變數。
  • 例子程式碼在這裡定義了一個全域性方法getUserInfo,這個全域性方法的訪問可以通過getApp().getUserInfo()。如果你開啟 pages/index/index.js,你會發現示例程式碼通過getApp()取得應用例項後呼叫了getUserInfo這個全域性方法
//獲取應用例項
const app = getApp()
...
//呼叫應用例項的方法獲取全域性資料
app.getUserInfo(function(userInfo){
  //更新資料
  that.setData({
    userInfo:userInfo
  })
})複製程式碼

那麼類似像onLaunch這樣的生命週期函式有哪些呢?還有onShow,onHide和onError。onShow和onHide分別是應用從後臺切換到前臺以及從前臺進入後臺時呼叫的。當你關閉小程式或者切換微信應用到別的應用時,微信並沒有直接幹掉小程式,小程式只是進入後臺而已,當你切換回來,小程式就又進入了前臺。這個機制其實和Android以及iOS的應用切換很像。onError顧名思義就是小程式發生指令碼錯誤或者api呼叫失敗是觸發的。注意:請不要在其他頁面呼叫生命週期函式

接下來我們看看 app.json,這個東東呢,就是小程式的應用全域性配置檔案。結構也很簡單:pages定義頁面的檔案路徑,window定義小程式整個視窗的一些元素,比如Title的文字,Title的顏色,視窗背景顏色等等。

{
  "pages":[
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "todos",
    "navigationBarTextStyle":"black"
  },
  "debug": true
}複製程式碼

比如在上面的配置下,視窗的展現形式是這樣的

現學現賣微信小程式開發(一)
在預設配置下視窗的表現

如果我們改動app.json 成為下面的樣子,那麼是什麼效果呢?

{
  "pages":[
    "pages/index/index",
    "pages/todos/todos"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#000",
    "navigationBarTitleText": "todo",
    "navigationBarTextStyle":"white",
    "backgroundColor": "#492b2b"
  },
  "debug": true
}複製程式碼

現學現賣微信小程式開發(一)
改動app.json後的效果

嗯,導航欄背景變成黑色了,文字白色,一切很完美。且慢,我們不是還新增了一個 "backgroundColor": "#492b2b" 嗎,它的效果怎麼沒有出來呢?你點選頭像進入log頁面後,再點選左上角返回會看到一個動畫,這個動畫的背景竟然是我們設定的視窗背景色!?

現學現賣微信小程式開發(一)
backgroundColor體現在介面切換時

但為毛在靜態介面上看不到呢,我猜想是由於Page擋在了背景前面,但是不是呢,我們來用試驗驗證一下。怎麼驗證呢,我們在window的設定中再加一個配置 "enablePullDownRefresh": "true",這個是啟用下拉重新整理的效果的開關,我們試一下,拖住介面往下拉,果然,視窗背景色在後面藏著呢!

現學現賣微信小程式開發(一)
下拉後露出了視窗背景色

同樣 backgroundTextStyle定義的是下拉背景字型、loading 圖的樣式(僅支援 dark/light)

在這個配置檔案中,我們還可以定義用於切換介面的工具欄(tab bar),我們也來試驗一下吧。

{
  "pages":[
    "pages/index/index",
    "pages/todos/todos"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#000",
    "navigationBarTitleText": "todo",
    "navigationBarTextStyle":"white",
    "backgroundColor": "#492b2b",
    "enablePullDownRefresh": "true"
  },
  "tabBar": {
    "list": [{
      "pagePath": "pages/index/index",
      "text": "首頁"
    }, {
      "pagePath": "pages/logs/logs",
      "text": "日誌"
    }]
  },
  "debug": true
}複製程式碼

現學現賣微信小程式開發(一)
配置tabBar後的效果

嗯嗯,很醜陋,但是畢竟顯示出來了。那麼問題來了,這個tabBar如何自定義呢?除了list屬性,它還提供color,selectedColor,backgroundColor,borderStyle和postion屬性。我們都設定一下

  "tabBar": {
    "list": [{
      "pagePath": "pages/index/index",
      "text": "首頁",
      "selectedIconPath": "assets/images/home.png"
    }, {
      "pagePath": "pages/logs/logs",
      "text": "日誌",
      "iconPath": "assets/images/log.png"
    }],
    "color": "#b0bec5",
    "backgroundColor": "#2196F3",
    "selectedColor": "#fff",
    "borderStyle": "#F8BBD0",
    "position": "bottom"
  }複製程式碼

現學現賣微信小程式開發(一)
自定義tabBar效果

還是比較醜,碼農加直男,只能湊活了。你可能發現我在list中一個新增的是selectedIconPath,一個新增的是iconPath。其實我是犯懶,不想再找兩個圖片而已。恰好首頁是預設選中的tab,那麼正好兩個圖示都能顯示出來。

除了tabBar,還可以設定一個debug屬性,預設是false,如果設定成true,那麼你在除錯的時候,會發現在console裡面顯示很多log資訊。其資訊有Page的註冊,頁面路由,資料更新,事件觸發等。這個開關在開發時建議開啟,在釋出時記著關閉哈。

現學現賣微信小程式開發(一)
debug設定成true會在console裡面顯示很多log資訊

再來看 app.wxss,估計你猜也猜得到,這個就是類似css的樣式表了。這個全域性樣式所有頁面都可以使用。

/**app.wxss**/
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 200rpx 0;
  box-sizing: border-box;
}複製程式碼

像我這麼愛折騰的人,對於這個css肯定要鼓搗一通,看看到底起什麼作用?我們首先加一個背景色,紅色比較顯眼,background-color: red;

現學現賣微信小程式開發(一)
首頁的變化

首頁下方有一片區域沒有著色,先不管它,點頭像進去看看。

現學現賣微信小程式開發(一)
日誌頁面的變化

這種變化說明這個container選擇器是應用於頁面的,根據頁面內容來決定高度,所以這個100%並不能填滿全屏。好在微信小程式可以接受css的大部分設定,如果把 height: 100%; 改成 height: 100vh; 就可以填滿全屏了。

頁面檔案

頁面檔案也很簡單,基本就是和資料夾同名的 .js.json.wxss 檔案,唯一多了一種型別就是 .wxml 檔案。.js檔案中定義一個Page函式,用於構建頁面檢視的邏輯,而.wxml描述頁面檢視的結構和佈局。首先看一下index.js:

var app = getApp()
Page({
  data: {
    motto: 'Hello World',
    userInfo: {}
  },
  //事件處理函式
  bindViewTap: function() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
  onLoad: function () {
    console.log('onLoad')
    var that = this
    //呼叫應用例項的方法獲取全域性資料
    app.getUserInfo(function(userInfo){
      //更新資料
      that.setData({
        userInfo:userInfo
      })
    })
  }
})複製程式碼

由上面的結構可以看出基本上Page函式是一個這樣的形式。它接受一個物件,這個物件有一些生命週期函式、事件處理函式和資料物件構成。也就是說上面的程式碼可以改寫成下面這樣的形式。

let app = getApp()
let pageParams = {
  data: {
    motto: 'Hello World',
    userInfo: {}
  },
  //事件處理函式
  bindViewTap: function() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
  onLoad: function () {
    console.log('onLoad')
    var that = this
    //呼叫應用例項的方法獲取全域性資料
    app.getUserInfo(function(userInfo){
      //更新資料
      that.setData({
        userInfo:userInfo
      })
    })
  }
}
Page(pageParams)複製程式碼

事實上我們更傾向於這麼寫,因為這樣的寫法可以使我們避免太多巢狀,以及對pageParams做更多靈活的操作。因為是個物件,我們可以寫成 pageParams.data = blablablapageParams.onLoad = someFunctionCall。對了,這個物件我也不知道叫什麼,自己給它起的名字而已,反正Page函式是需要這麼一個引數的。

那麼頁面的內建函式有哪些呢?可以參照下表,其中前5項屬於生命週期函式。

內建函式 作用 呼叫機制
onLoad 監聽頁面載入 生命週期內呼叫一次
onReady 監聽頁面初次渲染完成 生命週期內呼叫一次
onShow 監聽頁面顯示 每次開啟頁面都會呼叫一次
onHide 監聽頁面隱藏 當navigateTo或底部tab切換時呼叫
onUnload 監聽頁面解除安裝 當redirectTo或navigateBack的時候呼叫
onPullDownRefresh 監聽使用者下拉動作 使用者動作觸發
onReachBottom 頁面上拉觸底事件的處理函式 事件觸發
onShareAppMessage 使用者點選右上角分享 使用者點選觸發

具體可以參看微信官方文件給出的頁面生命週期示意圖

現學現賣微信小程式開發(一)
微信官方文件給出的頁面生命週期示意圖

再來看看 index.wxml,其實就是類似html的一個模版檔案,但是微信自己重造輪子的目的不是很清楚。這裡 class="container" 應用了我們的全域性樣式。

<!--index.wxml-->
<view class="container">
  <view  bindtap="bindViewTap" class="userinfo">
    <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
    <text class="userinfo-nickname">{{userInfo.nickName}}</text>
  </view>
  <view class="usermotto">
    <text class="user-motto">{{motto}}</text>
  </view>
</view>複製程式碼

事件繫結是通過在元件標籤內加 bindXXX=handler 來完成的,這個 handler 需要在pageParams物件中定義。 {{userInfo.nickName}} 是引用了我們在 index.js 中定義的資料物件的屬性。

index.json 也是蠻簡單,就是設定頁面的一些屬性,比如我們改寫一下的話:

{
    "navigationBarTitleText": "首頁"
}複製程式碼

導航欄文字就會變成我們設定的值。

現學現賣微信小程式開發(一)
設定導航欄文字

好的,到現在我們應該清楚了大概的微信小應用的基礎知識。下一節我們會嘗試著做我們的Todo應用了。

相關文章