微信小程式入門教程之四:API 使用

阮一峰發表於2020-11-02

今天是這個系列教程的最後一篇。

上一篇教程介紹了,小程式頁面如何使用 JavaScript 指令碼。有了指令碼以後,就可以呼叫微信提供的各種能力(即微信 API),從而做出千變萬化的頁面。本篇就介紹怎麼使用 API。

所有示例的完整程式碼,都可以從 GitHub 的程式碼倉庫下載。

一、WXML 渲染語法

前面說過,小程式的頁面結構使用 WXML 語言進行描述。

WXML 的全稱是微信頁面標籤語言(Weixin Markup Language),它不僅提供了許多功能標籤,還有一套自己的語法,可以設定頁面渲染的生效條件,以及進行迴圈處理。

微信 API 提供的資料,就通過 WXML 的渲染語法展現在頁面上。比如,home.js裡面的資料來源是一個陣列。


Page({
  data: {
    items: ['事項 A', '事項 B', '事項 C']
  }
});

上面程式碼中,Page()的引數配置物件的data.items屬性是一個陣列。通過資料繫結機制,頁面可以讀取全域性變數items,拿到這個陣列。

拿到陣列以後,怎樣將每一個陣列成員展現在頁面上呢?WXML 的陣列迴圈語法,就是一個很簡便的方法。

開啟home.wxml,改成下面的程式碼。


<view>
  <text class="title" wx:for="{{items}}">
    {{index}}、 {{item}}
   </text>
</view>

上面程式碼中,<text>標籤的wx:for屬性,表示當前標籤(<text>)啟用陣列迴圈,處理items陣列。陣列有多少個成員,就會生成多少個<text>。渲染後的頁面結構如下。


<view>
  <text>...</text>
  <text>...</text>
  <text>...</text>
</view>

在迴圈體內,當前陣列成員的位置序號(從0開始)繫結變數index,成員的值繫結變數item

開發者工具匯入專案程式碼,頁面渲染結果如下。

這個示例的完整程式碼,可以參考程式碼倉庫

WXML 的其他渲染語法(主要是條件判斷和物件處理),請檢視官方文件

二、客戶端資料儲存

頁面渲染用到的外部資料,如果每次都從伺服器或 API 獲取,有時可能會比較慢,使用者體驗不好。

小程式允許將一部分資料儲存在客戶端(即微信 App)的本地儲存裡面(其實就是自定義的快取)。下次需要用到這些資料的時候,就直接從本地讀取,這樣就大大加快了渲染。本節介紹怎麼使用客戶端資料儲存。

開啟home.wxml,改成下面的程式碼。


<view>
  <text class="title" wx:for="{{items}}">
    {{index}}、 {{item}}
   </text>
   <input placeholder="輸入新增事項" bind:input="inputHandler"/>
   <button bind:tap="buttonHandler">確定</button>
</view>

上面程式碼除了展示陣列items,還新增了一個輸入框和一個按鈕,用來接受使用者的輸入。背後的意圖是,使用者通過輸入框,為items陣列加入新成員。

開發者工具匯入專案程式碼,頁面渲染結果如下。

注意,輸入框有一個input事件的監聽函式inputHandler(輸入內容改變時觸發),按鈕有一個tap事件的監聽函式buttonHandler(點選按鈕時觸發)。這兩個監聽函式負責處理使用者的輸入。

然後,開啟home.js,程式碼修改如下。


Page({
  data: {
    items: [],
    inputValue: ''
  },
  inputHandler(event) {
    this.setData({
      inputValue: event.detail.value || ''
    });
  },
  buttonHandler(event) {
    const newItem = this.data.inputValue.trim();
    if (!newItem) return;
    const itemArr = [...this.data.items, newItem];
    wx.setStorageSync('items', itemArr);
    this.setData({ items: itemArr });
  },
  onLoad() {
    const itemArr = wx.getStorageSync('items') || []; 
    this.setData({ items: itemArr });
  }
});

上面程式碼中,輸入框監聽函式inputHandler()只做了一件事,就是每當使用者的輸入發生變化時,先從事件物件eventdetail.value屬性上拿到輸入的內容,然後將其寫入全域性變數inputValue。如果使用者刪除了輸入框裡面的內容,inputValue就設為空字串。

按鈕監聽函式buttonHandler()是每當使用者點選提交按鈕,就會執行。它先從inputValue拿到使用者輸入的內容,確定非空以後,就將其加入items陣列。然後,使用微信提供的wx.setStorageSync()方法,將items陣列儲存在客戶端。最後使用this.setData()方法更新一下全域性變數items,進而觸發頁面的重新渲染。

wx.setStorageSync()方法屬於小程式的客戶端資料儲存 API,用於將資料寫入客戶端儲存。它接受兩個引數,分別是鍵名和鍵值。與之配套的,還有一個wx.getStorageSync()方法,用於讀取客戶端儲存的資料。它只有一個引數,就是鍵名。這兩個方法都是同步的,小程式也提供非同步版本,請參考官方文件

最後,上面程式碼中,Page()的引數配置物件還有一個onLoad()方法。該方法屬於頁面的生命週期方法,頁面載入後會自動執行該方法。它只執行一次,用於頁面初始化,這裡的意圖是每次使用者開啟頁面,都通過wx.getStorageSync()方法,從客戶端取出以前儲存的資料,顯示在頁面上。

這個示例的完整程式碼,可以參考程式碼倉庫

必須牢記的是,客戶端儲存是不可靠的,隨時可能消失(比如使用者清理快取)。使用者換了一臺手機,或者本機重灌微信,原來的資料就丟失了。所以,它只適合儲存一些不重要的臨時資料,最常見的用途一般就是作為快取,加快頁面顯示。

三、遠端資料請求

小程式可以從外部伺服器讀取資料,也可以向伺服器傳送資料。本節就來看看怎麼使用小程式的網路能力。

微信規定,只有後臺登記過的伺服器域名,才可以進行通訊。不過,開發者工具允許開發時放鬆這個限制。

按照上圖,點選開發者工具右上角的三條橫線("詳情"),選中"不校驗合法域名、web-view(業務域名)、TLS 版本以及 HTTPS 證照" 。這樣的話,小程式在開發時,就可以跟伺服器進行通訊了。

下面,我們在本地啟動一個開發伺服器。為了簡單起見,我選用了 json-server 作為本地伺服器,它的好處是隻要有一個 JSON 資料檔案,就能自動生成 RESTful 介面。

首先,新建一個資料檔案db.json,內容如下。


{
  "items": ["事項 A", "事項 B", "事項 C"]
}

然後,確認本機安裝了 Node.js 以後,進入db.json所在的目錄,在命令列執行下面命令,啟動伺服器。


npx json-server db.json

正常情況下,這時你開啟瀏覽器訪問localhost:3000/items這個網址,就能看到返回了一個陣列["事項 A", "事項 B", "事項 C"]

接著,開啟home.js,程式碼修改如下。


Page({
  data: { items: [] },
  onLoad() {
    const that = this;
    wx.request({
      url: 'http://localhost:3000/items',
      success(res) {
        that.setData({ items: res.data });
      }
    });
  }
});

上面程式碼中,生命週期方法onLoad()會在頁面載入後自動執行,這時就會執行wx.request()方法去請求遠端資料。如果請求成功,就會執行回撥函式succcess(),更新頁面全域性變數items,從而讓遠端資料顯示在頁面上。

wx.request()方法就是小程式的網路請求 API,通過它可以傳送 HTTP 請求。它的引數配置物件最少需要指定url屬性(請求的網址)和succcess()方法(伺服器返回資料的處理函式)。其他引數請參考官方文件

開發者工具匯入專案程式碼,頁面渲染結果如下。它的初始資料是從伺服器拿到的。

這個示例的完整程式碼,可以參考程式碼倉庫

這個例子只實現了遠端資料獲取,json-server 實際上還支援資料的新增和刪改,大家可以作為練習,自己來實現。

四、<open-data>元件

如果要在頁面上展示當前使用者的身份資訊,可以使用小程式提供的<open-data>元件

開啟home.wxml檔案,程式碼修改如下。


<view>
  <open-data type="userAvatarUrl"></open-data>
  <open-data type="userNickName"></open-data>
</view>

上面程式碼中,<open-data>元件的type屬性指定所要展示的資訊型別,userAvatarUrl表示展示使用者頭像,userNickName表示使用者暱稱。

開發者工具匯入專案程式碼,頁面渲染結果如下,顯示你的頭像和使用者暱稱。

<open-data>支援的使用者資訊如下。

  • userNickName:使用者暱稱
  • userAvatarUrl:使用者頭像
  • userGender:使用者性別
  • userCity:使用者所在城市
  • userProvince:使用者所在省份
  • userCountry:使用者所在國家
  • userLanguage:使用者的語言

這個示例的完整程式碼,可以參考程式碼倉庫

<open-data>不需要使用者授權,也不需要登入,所以用起來很方便。但也是因為這個原因,小程式不允許使用者指令碼讀取<open-data>返回的資訊。

五、獲取使用者個人資訊

如果想拿到使用者的個人資訊,必須得到授權。官方建議,通過按鈕方式獲取授權。

開啟home.wxml檔案,程式碼修改如下。


<view>
  <text class="title">hello {{name}}</text>
  <button open-type="getUserInfo" bind:getuserinfo="buttonHandler">
    授權獲取使用者個人資訊
  </button>
</view>

上面程式碼中,<button>標籤的open-type屬性,指定按鈕用於獲取使用者資訊,bind:getuserinfo屬性表示點選按鈕會觸發getuserinfo事件,即跳出對話方塊,詢問使用者是否同意授權。

使用者點選"允許",指令碼就可以得到使用者資訊。

home.js檔案的指令碼程式碼如下。


Page({
  data: { name: '' },
  buttonHandler(event) {
    if (!event.detail.userInfo) return;
    this.setData({
      name: event.detail.userInfo.nickName
    });
  }
});

上面程式碼中,buttonHandler()是按鈕點選的監聽函式,不管使用者點選"拒絕"或"允許",都會執行這個函式。我們可以通過事件物件event有沒有detail.userInfo屬性,來判斷使用者點選了哪個按鈕。如果能拿到event.detail.userInfo屬性,就表示使用者允許讀取個人資訊。這個屬性是一個物件,裡面就是各種使用者資訊,比如頭像、暱稱等等。

這個示例的完整程式碼,可以參考程式碼倉庫

實際開發中,可以先用wx.getSetting()方法判斷一下,使用者是否已經授權過。如果已經授權過,就不用再次請求授權,而是直接用wx.getUserInfo()方法獲取使用者資訊。

注意,這種方法返回的使用者資訊之中,不包括能夠真正識別唯一使用者的openid屬性。這個屬性需要用到保密的小程式金鑰去請求,所以不能放在前端獲取,而要放在後端。這裡就不涉及了。

六、多頁面的跳轉

真正的小程式不會只有一個頁面,而是多個頁面,所以必須能在頁面之間實現跳轉。

app.json配置檔案的pages屬性就用來指定小程式有多少個頁面。


{
  "pages": [
    "pages/home/home",
    "pages/second/second"
  ],
  "window": ...
}

上面程式碼中,pages陣列包含兩個頁面。以後每新增一個頁面,都必須把頁面路徑寫在pages陣列裡面,否則就是無效頁面。排在第一位的頁面,就是小程式開啟時,預設展示的頁面。

新建第二個頁面的步驟如下。

第一步,新建pages/second目錄。

第二步,在該目錄裡面,新建檔案second.js,程式碼如下。


Page({});

第三步,新建第二頁的頁面檔案second.wxml,程式碼如下。


<view>
  <text class="title">這是第二頁</text>
  <navigator url="../home/home">前往首頁</navigator>
</view>

上面程式碼中,<navigator>就是連結標籤,相當於網頁標籤<a>,只要使用者點選就可以跳轉到url屬性指定的頁面(這裡是第一頁的位置)。

第四步,修改第一頁的頁面檔案home.wxml,讓使用者能夠點選進入第二頁。


<view>
  <text class="title">這是首頁</text>
  <navigator url="../second/second">前往第二頁</navigator>
</view>

開發者工具匯入專案程式碼,頁面渲染結果如下。

使用者點選"前往第二頁",就會看到第二個頁面。

這個示例的完整程式碼,可以參考程式碼倉庫

七、wx.navigateTo()

除了使用<navigator>元件進行頁面跳轉,小程式也提供了頁面跳轉的指令碼方法wx.navigateTo()

首先,開啟home.wxml檔案,程式碼修改如下。


<view>
  <text class="title">這是首頁</text>
  <button bind:tap="buttonHandler">前往第二頁</button>
</view>

開發者工具匯入專案程式碼,頁面渲染結果如下。

然後,開啟home.js檔案,程式碼修改如下。


Page({
  buttonHandler(event) {
    wx.navigateTo({
      url: '../second/second'
    });
  }
});

上面程式碼中,buttonHandler()是按鈕點選的監聽函式,只要使用者點選按鈕,就會呼叫wx.navigateTo()方法。該方法的引數是一個配置物件,該物件的url屬性指定了跳轉目標的位置,自動跳轉到那個頁面。

這個示例的完整程式碼,可以參考程式碼倉庫

寫到這裡,這個小程式入門教程就告一段落了,入門知識基本上都涉及了。下一步,大家可以閱讀小程式的官方教程使用文件,爭取對小程式 API 有一個整體的把握,然後再去看看各種實際專案的原始碼,應該就可以動手開發了。以後,我還會寫小程式的進階教程,包括雲開發,介紹如何寫小程式的後端,下次再見。

(完)

相關文章