1. 程式人生 > >小程式入門總結篇

小程式入門總結篇

整理於網路 http://blog.poetries.top/2018/08/09/xiaochengxu-note

一、小程式程式碼組成

前言

  • App() 必須在 app.js 中註冊,且不能註冊多個。
  • 編譯後的程式碼包大小需小於 1MB,否則程式碼包將上傳失敗。
  • 每個頁面需要手動在app.json中進行註冊,否則不能訪問。
  • app.jsonpages陣列的第一項代表小程式的初始頁面,小程式中新增/減少頁面,都需要對 pages 陣列進行修改。
  • 直接修改 this.data無效,無法改變頁面的狀態,還會造成資料不一致。
  • 單次設定的資料不能超過1024kB
    ,請儘量避免一次設定過多的資料。
  • 不要嘗試修改頁面棧,會導致路由以及頁面狀態錯誤。
  • tabBar只能配置最少2個、最多5個,tab 按陣列的順序排序。
  • 小程式頁面只能同時開啟 5 個,如果互動流程較長難以支援。
  • 同時只能存在 5 個url請求。
  • 無法跳轉小程式以外的url
  • 沒有cookie
  • 沒有開放載入web頁面
  • 沒有a標籤連結,不可巢狀iframe
  • 沒有window變數,但微信提供了wx全域性方法集
  • 事件繫結和條件渲染類似Angular,全部寫在WXML

1.1 主體

app.jsapp.jsonapp.wxss

三個檔案組成,放在根目錄

  • app.js 根目錄的app.js很有用,因為在它內部註冊的變數或方法,都是可以被所有頁面獲取到。可以監聽並處理小程式的生命週期、宣告全域性變數。其餘的.js文 件可以通過var app = getApp() 獲取其例項,呼叫其中定義的方法和變數,但不可以呼叫生命週期的方法
  • app.json是小程式的全域性配置
pages 配置小程式的組成頁面,第一個代表小程式的初始頁面
window  設定小程式的狀態列、標題欄、導航條、視窗背景顏色
tabBar  配置小程式tab欄的樣式和對應的頁面
  • app.wxss 是小程式的公共樣式表,可以在其他.wxss
    檔案中直接使用

app.json

"pages": [ //設定頁面的路徑
  "pages/index/index", //不需要寫index.wxml,index.js,index,wxss,框架會自動尋找並整合
  "pages/logs/logs"
],
"window": { //設定預設視窗的表現形式
  "navigationBarBackgroundColor": "#ffffff", //頂部導航欄背景色
  "navigationBarTextStyle": "black", //頂部導航文字的顏色 black/white
  "navigationBarTitleText": "微信介面功能演示", //頂部導航的顯示文字
  "backgroundColor": "#eeeeee", //視窗的背景色
  "backgroundTextStyle": "light", //下拉背景字型、loading 圖的樣式,僅支援 dark/light
  "enablePullDownRefresh": "false", //是否支援下拉重新整理 ,不支援的話就直接不寫!
  "disableScroll": true, //  設定true不能上下滾動,true/false,注意!只能在 page.json 中有效,無法在 app.json 中設定該項。
},
"tabBar": { //底部tab或者頂部tab的表現,是個陣列,最少配置2個,最多5個
  "list": [{ //設定tab的屬性,最少2個,最多5個
    "pagePath": "pages/index/index", //點選底部 tab 跳轉的路徑
    "text": "首頁", //tab 按鈕上的文字
    "iconPath": "../img/a.png", //tab圖片的路徑
    "selectedIconPath": "../img/a.png" //tab 在當前頁,也就是選中狀態的路徑
  }, {
    "pagePath": "pages/logs/logs",
    "text": "日誌"
  }],
  "color": "red", //tab 的字型顏色
  "selectedColor": "#673ab7", //當前頁 tab 的顏色,也就是選中頁的
  "backgroundColor": "#2196f3", //tab 的背景色
  "borderStyle": "white", //邊框的顏色 black/white
  "position": "bottom" //tab處於視窗的位置 top/bottom
  },
"networkTimeout": { //預設都是 60000 秒一分鐘
    "request": 10000, //請求網路超時時間 10000 秒
    "downloadFile": 10000, //連結伺服器超時時間 10000 秒
      "uploadFile": "10000", //上傳圖片 10000 秒
    "downloadFile": "10000" //下載圖片超時時間 10000 秒
  },
"debug": true //專案上線後,建議關閉此項,或者不寫此項

1.2 pages

pages資料夾裡是小程式的各個頁面,每個介面一般都由.wxml.wxss.js.json四個檔案組成,四個檔案必須是相同的名字和路徑

  • .js 是頁面的指令碼程式碼,通過Page()函式註冊頁面。可以指定頁面的初始資料、生命週期、事件處理等
  • .wxml 是頁面的佈局檔案,只能使用微信定義的元件
  • .wxss 是樣式表,需要注意
    • 尺寸單位:rpx 可以根據螢幕的寬頻進行自適應
    • 樣式匯入:@import匯入外聯樣式表,如:@import "test.wxss";
    • 定義在app.wxss中的全域性樣式,作用於每個頁面。定義在page.wxss檔案只作用於對應的頁面,會覆蓋app.wxss中相同的選擇器
  • .json 是頁面的配置檔案,只能設定app.json中的window配置內容,會覆蓋app.jsonwindow的相同配置項,即使不配置任何東西也需要寫{},否則會報錯

1.3 utils

utils 裡面包含一些公共的程式碼抽取的js檔案,作為模組方便使用。模組通過module.exports對外暴露介面

  • 其他地方使用是var utils = require('../../utils/util.js') 進行引用

二、檢視層 WXML

2.1 資料繫結

傳統的檢視和資料繫結

image.png

那麼微信小程式是通過什麼方法來管理檢視和物件繫結的呢,狀態模式-單向資料流

image.png

資料流向是單向的,即檢視變化不會影響物件狀態

  • 使用者觸發事件不僅要考慮當前UI元素更新,還會通過當前元素更新其他檢視。
  • 所以檢視上的資料都必須用過事件傳遞給物件,只有使用者操作檢視,才能獲取到資料,並更新物件狀態

image.png

.wxml 中的動態資料都來自Page中的data。資料繫結使用資料繫結使用雙大括號將變數包起來,可以作用於內容、元件屬性(需要在雙引號之內)、控制屬性(需要在雙引號之內)、關鍵字(需要在雙引號之內)

Page({
    data: {
        message: "Hello",
        id:0,
        status: true
    }
})
<view> {{message}} </view>
<view id="item-{{id}}"> </view>
<view wx:if="{{status}}"> </view>
<view hidden="{{status}}"> </checkbox>

還可以進行簡單的運算在大括號裡

<view hidden="{{status ? true : false}}"> Hidden </view>
<view> {{a + b}} + c </view> 
<view wx:if="{{num > 6}}"> </view>
<view>{{"hello" + word}}</view>

2.2 條件渲染

wx:if=”{{status}}”來判斷是否渲染程式碼塊

<view wx:if="{{status}}"> isShow </view>

還可以新增else

<view wx:if="{{num > 5}}"> A </view>
<view wx:elif="{{num > 2}}"> B </view>
<view wx:else> C </view>

2.3 列表渲染

  • 在元件上使用 wx:for屬性繫結一個數組,就可以渲染元件了
  • 預設情況下陣列的當前下標變數名為index,當前項的變數名為item
<view wx:for="{{array}}">
  {{index}}: {{item.message}}
</view>
Page({
  data: {
    array: ["AA","BB","CC"]
  }
})

使用 wx:for-item 可以指定陣列當前元素的變數名,使用 wx:for-index 可以指定陣列當前下標的變數名

<view wx:for="{{array}}" wx:for-index="num" wx:for-item="itemName">
  {{num}}: {{itemName}}
</view>

2.4 模板template

  • name 定義元件模版的名稱,引用模版的時候使用 is 屬性指定模版的名字,is 可以進行簡單的三目運算,需要傳入模版需要的 data 資料。
  • 因為模版擁有自己的作用域,所以只能使用 data 傳入資料,而不接受雙花括號的寫法
<template name="msgItem">
<view>
<text> {{index}}: {{msg}} </text>
<text> Time: {{time}} </text>
</view>
</template>

<!-- 其他程式碼 -->
<template is="msgItem" data="{{...item}}"/>

2.5 公共模組的引用

  • WXML 提供 importinclude 兩種檔案引用方式。
  • import 有作用域的概念,不能多重引用
<!-- B.wxml -->
<import src="a.wxml"/>

<!-- A.wxml -->
<template name="A">
 <text> A template </text>
</template>

include 就可以多重引用

<!--引用 header、其中 header.wxml 中也引用了 footer.wxml-->
<include src="header.wxml"/>
<view> body </view>

<!-- header.wxml -->
<view> header </view>
<include src="footer.wxml"/>

2.6 事件

  • 名稱以 bind 開頭的事件不阻止冒泡,名稱以 catch 開頭的事件冒泡是阻止的。如 bindTapcatchTab
  • WXML 中,可以使用 dataset 定義data中的資料,會通過事件傳遞。它的事件以 data-開頭,多個單詞以 - 連結,如 data-a-b

三、生命週期

3.1 App()應用生命週期

image

  • 使用者首次開啟小程式,觸發 onLaunch(全域性只觸發一次)。
  • 小程式初始化完成後,觸發onShow方法,監聽小程式顯示。
  • 小程式從前臺進入後臺,觸發 onHide方法。
  • 小程式從後臺進入前臺顯示,觸發 onShow方法。
  • 小程式後臺執行一定時間,或系統資源佔用過高,會被銷燬。
  • 小程式出錯,觸發onError

前臺、後臺定義: 當用戶點選左上角關閉,或者按了裝置 Home 鍵離開微信,小程式並沒有直接銷燬,而是進入了後臺;當再次進入微信或再次開啟小程式,又會從後臺進入前臺

//app.js
App({
  onLaunch: function() { 
      //小程式初始化(全域性只觸發一次)
  },
  onShow: function() {
      //小程式顯示
  },
  onHide: function() {
      //小程式隱藏
  },
  onError: function(msg) {
      //小程式錯誤
  },
})
//其他 開發者可以新增任意的函式或資料到 Object 引數中,用 this 可以訪問

3.2 Page頁面生命週期

每個頁面也有自己的生命週期

image

  • 小程式註冊完成後,載入頁面,觸發onLoad方法。
  • 頁面載入後觸發onShow方法,顯示頁面。
  • 首次顯示頁面,會觸發onReady方法,渲染頁面元素和樣式,一個頁面只會呼叫一次。
  • 當小程式後臺執行或跳轉到其他頁面時,觸發onHide方法。
  • 當小程式有後臺進入到前臺執行或重新進入頁面時,觸發onShow方法。
  • 當使用重定向方法wx.redirectTo(OBJECT)或關閉當前頁返回上一頁wx.navigateBack(),觸發onUnload
//index.js
Page({
  onLoad: function(options) {
    //頁面載入-----(一個頁面只會呼叫一次)
  },
  onReady: function() {
    //頁面渲染-----(一個頁面只會呼叫一次)
  },
  onShow: function() {
    //頁面顯示-----(每次開啟頁面都會呼叫一次)
  },
  onHide: function() {
    //頁面隱藏-----(當navigateTo或底部tab切換時呼叫)
  },
  onUnload: function() {
    //頁面解除安裝-----(當redirectTo或navigateBack的時候呼叫)
  },
})
//其他 開發者可以新增任意的函式或資料到 object 引數中,在頁面的函式中用 this 可以訪問

3.3 應用生命週期影響頁面生命週期

image.png

  • 小程式初始化完成後,頁面首次載入觸發onLoad,只會觸發一次。
  • 當小程式進入到後臺,先執行頁面onHide方法再執行應用onHide方法。
  • 當小程式從後臺進入到前臺,先執行應用onShow方法再執行頁面onShow方法

四、小程式限制

4.1 程式限制

  • 指令碼內不能使用window等物件
  • zepto/jquery 會使用到window物件和document物件,所以無法使用。
  • 樣式表不支援級聯選擇器
  • 本地資源無法通過 css 獲取 background-image可以使用網路圖片,或者 base64,或者使用標籤
  • 不支援 A 標籤,無法開啟普通網頁

4.2 數量限制

  • 底部或頂部可以新增tab按鈕區域 tabBar 是一個數組,只能配置最少2個、最多5個 tabtab按陣列的順序排序。
  • 一個應用同時只能開啟5個頁面
  • 小程式的wx.request請求最開始最大併發數是5個,後來,估計隨著用小程式的越來越多,總之,就是增加到了10個

4.3 大小限制

  • tabBar 上面的按鈕 iconPath 圖片路徑,icon大小限制為40kb
  • tabBar 上面的按鈕 selectedIconPath選中時的圖片路徑,icon 大小限制為40kb
  • setData 頁面傳遞資料單次設定的資料不能超過1024kB
  • setStorage 本地快取最大為10MB
  • 小程式原始碼打包後的大小限制為1M

五、路由

  • 微信路由介面有三個,分別是wx.redirectTowx.navigateTowx.switchTab
    wx.navigateTo全域性最多呼叫5次
  • 如果某頁面設定為tab頁,則只支援wx.switchTab,不支援其他兩種路由方式訪問

5.1 哪些情況會觸發頁面跳轉

  • 小程式啟動,初始化第一個頁面
  • 開啟新頁面,呼叫 API wx.navigateTo 或使用<navigator />元件
  • 頁面重定向,呼叫 API wx.redirectTo 或使用<navigator />元件
  • 頁面返回,呼叫 API wx.navigateBack或使用者按左上角返回按鈕
  • tarbar切換

5.2 如何跳轉頁面

  • 使用wx.navigateTo介面跳轉,原頁面保留
wx.navigateTo({
  //目的頁面地址
  url: 'pages/logs/index',
  success: function(res){},
  ...
})
  • 使用wx.redirectTo介面跳轉,關閉原頁面,不能返回
wx.redirectTo({
  //目的頁面地址
  url: 'pages/logs/index',
  success: function(res){},
  ...
})

5.3 使用元件

<navigator url="pages/logs/index" hover-class="navigator-hover">跳轉</navigator>

當該元件新增redirect屬性時,等同於wx.redirectTo介面;預設redirect屬性為false,等同於wx.navigateTo介面

使用者點選左上角返回按鈕,或呼叫wx.navigateBack介面返回上一頁

wx.navigateBack({
    delta: 1
})

delta為1時表示返回上一頁,為2時表示上上一頁,以此類推;如果dalta大於已開啟的頁面總數,則返回到首頁。返回後,元介面會銷燬

5.4 頁面跳轉傳值

url?key=value&key1=value1

傳遞的引數沒有被URIEncode,傳遞中文沒有亂碼

5.5 如何正確使用頁面跳轉

官方規定小程式最多隻能有五個頁面同時存在,意思是在不關閉頁面的情況,最多新開五個頁面,頁面深度為5

  • 對於可逆操作,使用wx.navigateTo,比如從首頁跳轉到二級頁面,從二級頁面返回是不需要重新渲染首頁
  • 對於不可逆操作,使用wx.redirectTo,比如使用者登入成功後,關閉登入頁面,不能返回到登入介面。
  • 對於一些介紹性等不常用頁面wx.redirectTowx.navigatrBack
  • 不要在首頁使用wx.redirectTo,這樣會導致應用無法返回首頁

5.6 頁面棧

  • 頁面棧以棧(先進後出)的形式維護頁面與頁面之間的關係
  • 小程式提供了getCurrentPages()函式獲取頁面棧,第一個元素為首頁,最後一個元素為當前頁面

使用wx.navigateTo每新開一個頁面,頁面棧大小加1,直到頁面棧大小為5為止

image.png

使用wx.navigateTo重複開啟介面

image.png

假如使用wx.navigateTo從四級頁面跳轉到二級頁面,此時會在頁面棧頂新增一個與二級頁面初始狀態一樣的介面,但兩個頁面狀態是獨立的。頁面棧大小會加1,如果頁面棧大小為5,則wx.navigateTo無效

使用wx.redirectTo重定向

image.png

假如使用wx.redirectTo從四級頁面重定向到二級頁面,此時會將關閉四級頁面,並使用二級頁面替換四級頁面,但兩個頁面狀態是獨立的。此時的頁面棧大小不變,請注意和使用wx.navigateTo的區別

使用wx.navigateBack返回

image.png

總結

  • wx.navigateTo會增加頁面棧大小,直到頁面棧大小為5
  • wx.redirectTo不會增加頁面棧大小
  • wx.navigateBack會減少頁面棧大小,直到頁面棧大小為1

六、資料通訊

6.1 頁面之間的通訊

  • 使用全域性變數 app.globalData
  • 使用本地快取 wx.setStorageSync
  • url傳遞**
// A頁面-傳遞資料

// 需要注意的是,wx.switchTab 中的 url 不能傳引數。
wx.navigateTo({
   url:'../pageD/pageD?name=raymond&gender=male'
})

// B頁面-接收資料//

//通過onLoad的option...

Page({
onLoad: function(option){
 console.log(option.name +'is'+ option.gender)// raymond is male
  this.setData({option: option })
}})

6.2 引數傳遞

6.2.1 小程式傳遞引數的方式

1、通過在App.js中設定全域性變數

通常把不會更改的資料放在app.jsData中,在各個頁面中都可以通過APP例項獲取Data資料

var app = getApp();
var data = app.data;

2、通過拼接URL直接傳遞

wx.navigateTo({})URL攜帶引數

wx.navigateTo({
  url: 'test?id=1'
});

在wxml中使用navigator跳轉url傳遞引數

程式碼如下,將要傳遞到另一個頁面的字串testId的值賦值到url中

<navigator class="test-item" url="../../pages/test/test?testId={{testData.testId}}"></navigator>

js頁面中onLoad方法中接收

Page({
  onLoad: function(options) {
      var testId = options.testId
      console.log(testId)
  }
})

navigator跳轉url傳遞陣列

如果一個頁面要將一個數組,如相簿列表傳遞到另一個頁面

<navigator class="test-item" url="../../pages/test/test?albumList={{testData.albumList}}"></navigator>

傳遞到js後從options中得到的是個字串,每個圖片的url通過','分隔,所以此時還需要對其進行處理,重新組裝為陣列

Page({
    data: {
         // 相簿列表資料
        albumList: [],
    },    
    onLoad: function (options) {
        var that = this;

        that.setData({
            albumList: options.albumList.split(",")
        });
    }
})

3、在wxml中繫結事件後,通過data-hi="引數"的方式傳遞

這種方式一般是在wxml中繫結事件,同時設定需要傳遞的資料,如果需要傳遞多個,可以寫多個data-[引數]的方式進行傳遞

<view bindtap="clickMe" data-testId={{testId}}">
    ...
</view>

在js頁面中自定義方法clickMe中接收

Page({
    clickMe: function(event) {
        var testId = event.currentTarget.dataset.testid;
        wx.navigateTo({
            url: '../../pages/test/test'
        })
    }
})

wxml中配置data-albumlist傳遞陣列

<view bindtap="clickMe" data-albumlist={{testData.albumList}}">
    
</view>
在js頁面中自定義方法clickMe中接收

Page({
    clickMe: function(event) {
        var albumList = event.currentTarget.dataset.albumlist.split(",");
        wx.navigateTo({
            url: '../../pages/test/test'
        })
    }
})

4、通過資料快取儲存再獲取

wx.setStorageSync(KEY,DATA)儲存資料

try {
  wx.setStorageSync('key', 'value')
} catch (e) {    
}

wx.getStorageSync(KEY)獲取資料

try {
  var value = wx.getStorageSync('key')
  if (value) {
    // Do something with return value
  }
} catch (e) {
   // Do something when catch error
}
或
wx.getStorage({
  key: 'key',
  success: function(res) {
     console.log(res.data)
  }
})

七、疑問彙總

為什麼指令碼內不能使用window等物件

  • 頁面的指令碼邏輯是在JsCore中執行,JsCore是一個沒有視窗物件的環境,所以不能在指令碼中使用window,也無法在指令碼中操作元件

為什麼 zepto/jquery 無法使用

  • zepto/jquery 會使用到window物件和document物件,所以無法使用

wx.navigateTo無法開啟頁面

  • 一個應用同時只能開啟5個頁面,當已經打開了5個頁面之後,wx.navigateTo不能正常開啟新頁面。請避免多層級的互動方式,或者使用wx.redirectTo

樣式表不支援級聯選擇器

  • WXSS支援以.開始的類選擇器

本地資源無法通過 css 獲取

  • background-image:可以使用網路圖片,或者 base64,或者使用<image/>標籤

如何修改視窗的背景色

  • 使用 page 標籤選擇器,可以修改頂層節點的樣式
page { 
  display: block; 
  min-height: 100%; 
  background-color: red;
}

為什麼上傳不成功

  • 為了提升體驗流暢度,編譯後的程式碼包大小需小於 1MB ,大於 1MB 的程式碼包將上傳失敗

HTTPS 請求不成功

  • tls 僅支援 1.2 及以上版本

微信小程式支援fetch或者promise嗎?

  • promise工具目前不支援,fetch 客戶端不支援 工具下個版本保持統一

wx.request的POST方法的引數傳輸伺服器接收不到的bug

  • wx.request postcontent-type 預設為 ‘application/json '
  • 如果伺服器沒有用到 json 解釋的話,可以把 content-type 設定回 urlencoded
wx.request({
....
method: "POST",
header: {
"content-type": "application/x-www-form-urlencoded"
},
...
})

wx.uploadFile在手機上返回http碼403

  • 安卓的微信升級到6.5.2及其以上版本

小程式SVG支援嗎?

  • image的src放遠端svg可以,background-image裡也可以

ipad不能使用小程式?

  • 暫時不支援ipad開啟小程式

請問小程式頁內支援長按儲存圖片或分享圖片嗎?

  • 目前沒有這個功能

微信小程式不支援cookie

  • 使用Reids儲存session

有些手機不支援Object.assign方法,如果使用了該方法會出現莫名其妙的報錯(並不會提示Object.assign is not function,而是導致呼叫了Object.assign方法的方法不能被呼叫)!

直接寫一個合併物件的方法

function assignObject(o, n) {
    for (var p in n) {
        if (n.hasOwnProperty(p) && (!o.hasOwnProperty(p)))
            o[p] = n[p];
    }
}

八、小程式元件

image.png

九、參考

 



作者:poetries
連結:https://www.jianshu.com/p/b6f97a99d281
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。