小程序模板網(wǎng)

微信小程序運(yùn)行流程看這篇就夠了

發(fā)布時(shí)間:2018-05-18 10:21 所屬欄目:小程序開(kāi)發(fā)教程

一.微信小程序是啥

本質(zhì)其實(shí)就是(混合)的app 介于web app與native 原生app之間,具備豐富的調(diào)用手機(jī)各種功能的接口,同時(shí)又具備靈活性,跨平臺(tái)

1. 運(yùn)行環(huán)境差異

微信小程序運(yùn)行在三端:iOS、Android 和 用于調(diào)試的開(kāi)發(fā)者工具。

三端的腳本執(zhí)行環(huán)境以及用于渲染非原生組件的環(huán)境是各不相同的:

  • 在 iOS 上,小程序的 javascript 代碼是運(yùn)行在 JavaScriptCore 中,是由 WKWebView 來(lái)渲染的,環(huán)境有 iOS8、iOS9、iOS10 
  • 在 Android 上,小程序的 javascript 代碼是通過(guò) X5 JSCore來(lái)解析,是由 X5 基于 Mobile Chrome 53/57 內(nèi)核來(lái)渲染的 
  • 在 開(kāi)發(fā)工具上, 小程序的 javascript 代碼是運(yùn)行在 nwjs 中,是由 Chrome Webview 來(lái)渲染的來(lái)自官方文檔說(shuō)明

2.小程序目錄結(jié)

project
├── pages
|   ├── index
|   |   ├── index.json  index 頁(yè)面配置
|   |   ├── index.js    index 頁(yè)面邏輯
|   |   ├── index.wxml  index 頁(yè)面結(jié)構(gòu)
|   |   └── index.wxss  index 頁(yè)面樣式表
|   └── log
|       ├── log.json    log 頁(yè)面配置
|       ├── log.wxml    log 頁(yè)面邏輯
|       ├── log.js      log 頁(yè)面結(jié)構(gòu)
|       └── log.wxss    log 頁(yè)面樣式表
├── app.js              小程序邏輯
├── app.json            小程序公共設(shè)置
└── app.wxss            小程序公共樣式表

3.為什么小程序比較快

二、小程序架構(gòu)

微信小程序的框架包含兩部分View視圖層(可能存在多個(gè))、App Service邏輯層(一個(gè)),View層用來(lái)渲染頁(yè)面結(jié)構(gòu),AppService層用來(lái)邏輯處理、數(shù)據(jù)請(qǐng)求、接口調(diào)用,它們?cè)趦蓚€(gè)線(xiàn)程里運(yùn)行。

視圖層使用WebView渲染,邏輯層使用JSCore運(yùn)行。

視圖層和邏輯層通過(guò)系統(tǒng)層的WeixinJsBridage進(jìn)行通信,邏輯層把數(shù)據(jù)變化通知到視圖層,觸發(fā)視圖層頁(yè)面更新,視圖層把觸發(fā)的事件通知到邏輯層進(jìn)行業(yè)務(wù)處理。

重點(diǎn)講一下wxs :

由于view 與  App Service是不同線(xiàn)程,之前是傳遞數(shù)據(jù),當(dāng)遇到一些數(shù)據(jù)需要在view中處理時(shí),就可以用wxs來(lái)處理,如下所示定義 <wxs module="tools">,使用說(shuō)明

index.js


//獲取應(yīng)用實(shí)例
const app = getApp()
Page({
  data: {
    motto: 'Hello World',
    userInfo: {},
    hasUserInfo: false
  },
  //事件處理函數(shù)
  bindViewTap: function() {
  },
  onLoad: function() {
  }
})

<!--index.wxml-->
<view class="container">
  <view class="usermotto">
    <text class="user-motto">{{tools.bar(motto)}}</text>
    <text class="user-motto">{{tools.foo}}</text>
  </view>
  <wxs module="tools">
  var foo = "'hello world' from comm.wxs";
  var bar = function(d) {
    return '啥子玩意'+d;
  }
  module.exports = {
    foo: foo,
    bar: bar
  };
  </wxs>
</view>

三、小程序啟動(dòng)加載

運(yùn)行機(jī)制

小程序啟動(dòng)會(huì)有兩種情況,一種是「冷啟動(dòng)」,一種是「熱啟動(dòng)」。 假如用戶(hù)已經(jīng)打開(kāi)過(guò)某小程序,然后在一定時(shí)間內(nèi)再次打開(kāi)該小程序,此時(shí)無(wú)需重新啟動(dòng),只需將后臺(tái)態(tài)的小程序切換到前臺(tái),這個(gè)過(guò)程就是熱啟動(dòng);冷啟動(dòng)指的是用戶(hù)首次打開(kāi)或小程序被微信主動(dòng)銷(xiāo)毀后再次打開(kāi)的情況,此時(shí)小程序需要重新加載啟動(dòng)。

更新機(jī)制

小程序冷啟動(dòng)時(shí)如果發(fā)現(xiàn)有新版本,將會(huì)異步下載新版本的代碼包,并同時(shí)用客戶(hù)端本地的包進(jìn)行啟動(dòng),即新版本的小程序需要等下一次冷啟動(dòng)才會(huì)應(yīng)用上。 如果需要馬上應(yīng)用最新版本,可以使用wx.getUpdateManager API 進(jìn)行處理。

運(yùn)行機(jī)制

  • 小程序沒(méi)有重啟的概念
  • 當(dāng)小程序進(jìn)入后臺(tái),客戶(hù)端會(huì)維持一段時(shí)間的運(yùn)行狀態(tài),超過(guò)一定時(shí)間后(目前是5分鐘)會(huì)被微信主動(dòng)銷(xiāo)毀
  • 當(dāng)短時(shí)間內(nèi)(5s)連續(xù)收到兩次以上收到系統(tǒng)內(nèi)存告警,會(huì)進(jìn)行小程序的銷(xiāo)毀

四、View (頁(yè)面視圖)

視圖層由 WXML 與 WXSS 編寫(xiě),由組件來(lái)進(jìn)行展示。

將邏輯層的數(shù)據(jù)反應(yīng)成視圖,同時(shí)將視圖層的事件發(fā)送給邏輯層。

1、View - WXML

wxml編譯器:wcc 把wxml文件 轉(zhuǎn)為 js 執(zhí)行方式:wcc index.wxml

2、View - WXSS

  • WXSS(WeiXin Style Sheets)
  • wxss編譯器:wcsc 把wxss文件轉(zhuǎn)化為 js 執(zhí)行方式: wcsc index.wxss

3、View - Component

  • 小程序的組件基于Web Component標(biāo)準(zhǔn)

  • 使用Polymer框架實(shí)現(xiàn)Web Component

4、View - Native Component

  • 目前Native實(shí)現(xiàn)的組件有 <canvas/> <video/> <map/> <textarea/>
  • Native組件層在WebView層之上

五、WebView預(yù)加載

每次小程序進(jìn)入除了當(dāng)前頁(yè)面,Native預(yù)先額外加載一個(gè)WebView

當(dāng)打開(kāi)指定頁(yè)面時(shí),用默認(rèn)數(shù)據(jù)直接渲染,請(qǐng)求數(shù)據(jù)回來(lái)時(shí)局部更新

返回顯示歷史View

退出小程序,View狀態(tài)不銷(xiāo)毀

六、App Service(邏輯層)

邏輯層將數(shù)據(jù)進(jìn)行處理后發(fā)送給視圖層,同時(shí)接受視圖層的事件反饋

1、App( ) 小程序的入口;Page( ) 頁(yè)面的入口

3、提供豐富的 API,如微信用戶(hù)數(shù)據(jù),掃一掃,支付等微信特有能力。

4、每個(gè)頁(yè)面有獨(dú)立的作用域,并提供模塊化能力。

5、數(shù)據(jù)綁定、事件分發(fā)、生命周期管理、路由管理

運(yùn)行環(huán)境

IOS - JSCore

Android - X5 JS解析器

DevTool - nwjs Chrome 內(nèi)核

1、App Service - Binding

  • 數(shù)據(jù)綁定使用 Mustache 語(yǔ)法(雙大括號(hào))將變量包起來(lái),動(dòng)態(tài)數(shù)據(jù)均來(lái)自對(duì)應(yīng) Page 的 data,可以通過(guò)setData方法修改數(shù)據(jù)。
  • 事件綁定的寫(xiě)法同組件的屬性,以 key、value 的形式,key 以bind或catch開(kāi)頭,然后跟上事件的類(lèi)型,如bindtap, catchtouchstart,value 是一個(gè)字符串,需要在對(duì)應(yīng)的 Page 中定義同名的函數(shù)。

2、App Service - Life Cylce

3、App Service - API

API通過(guò)WeixinJSBridge和Native 進(jìn)行通信

4、App Service - Router

  • navigateTo(OBJECT)

保留當(dāng)前頁(yè)面,跳轉(zhuǎn)到應(yīng)用內(nèi)的某個(gè)頁(yè)面,使用navigateBack可以返回到原頁(yè)面。頁(yè)面路徑只能是五層

  • redirectTo(OBJECT)

關(guān)閉當(dāng)前頁(yè)面,跳轉(zhuǎn)到應(yīng)用內(nèi)的某個(gè)頁(yè)面。

  • navigateBack(OBJECT)

關(guān)閉當(dāng)前頁(yè)面,返回上一頁(yè)面或多級(jí)頁(yè)面。可通過(guò) getCurrentPages()) 獲取當(dāng)前的頁(yè)面棧,決定需要返回幾層。

五、小程序開(kāi)發(fā)經(jīng)驗(yàn)

1、小程序存在的問(wèn)題

小程序仍然使用WebView渲染,并非原生渲染

需要獨(dú)立開(kāi)發(fā),不能在非微信環(huán)境運(yùn)行 。

開(kāi)發(fā)者不可以擴(kuò)展新組件。

依賴(lài)瀏覽器環(huán)境的js庫(kù)不能使用,因?yàn)槭荍SCore執(zhí)行的,沒(méi)有window、document對(duì)象。

WXSS中無(wú)法使用本地(圖片、字體等)。

WXSS轉(zhuǎn)化成js 而不是css。

WXSS不支持級(jí)聯(lián)選擇器。

小程序無(wú)法打開(kāi)頁(yè)面,無(wú)法拉起APP。

2、小程序的優(yōu)點(diǎn)

提前新建WebView,準(zhǔn)備新頁(yè)面渲染。

View層和邏輯層分離,通過(guò)數(shù)據(jù)驅(qū)動(dòng),不直接操作DOM。

使用Virtual DOM,進(jìn)行局部更新。

全部使用https,確保傳輸中安全。

加入rpx單位,隔離設(shè)備尺寸,方便開(kāi)發(fā)。


rpx(responsive pixel):
可以根據(jù)屏幕寬度進(jìn)行自適應(yīng)。規(guī)定屏幕寬為750rpx。
如在 iPhone6 上,屏幕寬度為375px,共有750個(gè)物理像素,則750rpx = 375px = 750物理像素,
1rpx = 0.5px = 1物理像素。
設(shè)備          rpx換算px (屏幕寬度/750)  px換算rpx (750/屏幕寬度)
iPhone5      1rpx = 0.42px           1px = 2.34rpx
iPhone6      1rpx = 0.5px            1px = 2rpx
iPhone6Plus  1rpx = 0.552px          1px = 1.81rpx

七、代碼運(yùn)行

運(yùn)行時(shí),外面包裹define,代碼作為回到,當(dāng)調(diào)用回調(diào)時(shí),只傳入前面三個(gè)值,由于后面的變量都是局部定義的變量,就屏蔽了(window,document等這些變量.

其中O就是上面define('app.js',callback),的回調(diào),回調(diào)值傳入了三個(gè)參數(shù),屏蔽了其他屬性

八、優(yōu)化建議(官方建議)

setData 工作原理

小程序的視圖層目前使用 WebView 作為渲染載體,而邏輯層是由獨(dú)立的 JavascriptCore 作為運(yùn)行環(huán)境。在架構(gòu)上,WebView 和 JavascriptCore 都是獨(dú)立的模塊,并不具備數(shù)據(jù)直接共享的通道。當(dāng)前,視圖層和邏輯層的數(shù)據(jù)傳輸,實(shí)際上通過(guò)兩邊提供的 evaluateJavascript 所實(shí)現(xiàn)。即用戶(hù)傳輸?shù)臄?shù)據(jù),需要將其轉(zhuǎn)換為字符串形式傳遞,同時(shí)把轉(zhuǎn)換后的數(shù)據(jù)內(nèi)容拼接成一份 JS 腳本,再通過(guò)執(zhí)行 JS 腳本的形式傳遞到兩邊獨(dú)立環(huán)境。

而 evaluateJavascript 的執(zhí)行會(huì)受很多方面的影響,數(shù)據(jù)到達(dá)視圖層并不是實(shí)時(shí)的。

常見(jiàn)的 setData 操作錯(cuò)誤

1. 頻繁的去 setData

在我們分析過(guò)的一些案例里,部分小程序會(huì)非常頻繁(毫秒級(jí))的去 setData ,其導(dǎo)致了兩個(gè)后果:

  • Android 下用戶(hù)在滑動(dòng)時(shí)會(huì)感覺(jué)到卡頓,操作反饋延遲嚴(yán)重,因?yàn)?JS 線(xiàn)程一直在編譯執(zhí)行渲染,未能及時(shí)將用戶(hù)操作事件傳遞到邏輯層,邏輯層亦無(wú)法及時(shí)將操作處理結(jié)果及時(shí)傳遞到視圖層;
  • 渲染有出現(xiàn)延時(shí),由于 WebView 的 JS 線(xiàn)程一直處于忙碌狀態(tài),邏輯層到頁(yè)面層的通信耗時(shí)上升,視圖層收到的數(shù)據(jù)消息時(shí)距離發(fā)出時(shí)間已經(jīng)過(guò)去了幾百毫秒,渲染的結(jié)果并不實(shí)時(shí);

2. 每次 setData 都傳遞大量新數(shù)據(jù)

由 setData 的底層實(shí)現(xiàn)可知,我們的數(shù)據(jù)傳輸實(shí)際是一次 evaluateJavascript 腳本過(guò)程,當(dāng)數(shù)據(jù)量過(guò)大時(shí)會(huì)增加腳本的編譯執(zhí)行時(shí)間,占用 WebView JS 線(xiàn)程,

3. 后臺(tái)態(tài)頁(yè)面進(jìn)行 setData

當(dāng)頁(yè)面進(jìn)入后臺(tái)態(tài)(用戶(hù)不可見(jiàn)),不應(yīng)該繼續(xù)去進(jìn)行 setData ,后臺(tái)態(tài)頁(yè)面的渲染用戶(hù)是無(wú)法感受的,另外后臺(tái)態(tài)頁(yè)面去 setData 也會(huì)搶占前臺(tái)頁(yè)面的執(zhí)行。

圖片資源

  • 目前圖片資源的主要性能問(wèn)題在于大圖片和長(zhǎng)列表圖片上,這兩種情況都有可能導(dǎo)致 iOS 客戶(hù)端內(nèi)存占用上升,從而觸發(fā)系統(tǒng)回收小程序頁(yè)面。
  • 在 iOS 上,小程序的頁(yè)面是由多個(gè) WKWebView 組成的,在系統(tǒng)內(nèi)存緊張時(shí),會(huì)回收掉一部分 WKWebView。從過(guò)去我們分析的案例來(lái)看,大圖片和長(zhǎng)列表圖片的使用會(huì)引起 WKWebView 的回收。

代碼包大小的優(yōu)化

開(kāi)發(fā)者在實(shí)現(xiàn)業(yè)務(wù)邏輯同時(shí)也有必要盡量減少代碼包的大小,因?yàn)榇a包大小直接影響到下載速度,從而影響用戶(hù)的首次打開(kāi)體驗(yàn)。除了代碼自身的重構(gòu)優(yōu)化外,還可以從這兩方面著手優(yōu)化代碼大小:

  1. 分包加載

    對(duì)小程序進(jìn)行分包,可以?xún)?yōu)化小程序首次啟動(dòng)的下載時(shí)間
  2. 清理沒(méi)有使用到的代碼和資源

目前小程序打包是會(huì)將工程下所有文件都打入代碼包內(nèi),也就是說(shuō),這些沒(méi)有被實(shí)際使用到的庫(kù)文件和資源也會(huì)被打入到代碼包里,從而影響到整體代碼包的大小。

預(yù)先加載數(shù)據(jù)

原理

小程序在啟動(dòng)時(shí),會(huì)直接加載所有頁(yè)面邏輯代碼進(jìn)內(nèi)存,即便 page2 可能都不會(huì)被使用。在 page1 跳轉(zhuǎn)至 page2 時(shí),page1 的邏輯代碼 Javascript 數(shù)據(jù)也不會(huì)從內(nèi)存中消失。page2 甚至可以直接訪(fǎng)問(wèn) page1 中的數(shù)據(jù)。

小程序的這種機(jī)制差異正好可以更好的實(shí)現(xiàn)預(yù)加載。通常情況下,我們習(xí)慣將數(shù)據(jù)拉取寫(xiě)在 onLoad 事件中。但是小程序的 page1 跳轉(zhuǎn)到 page2,到 page2 的 onLoad 是存在一個(gè) 300ms ~ 400ms 的延時(shí)的。如下圖:

因?yàn)樾〕绦虻奶匦裕耆梢栽?page1 中預(yù)先拿取數(shù)據(jù),然后在 page2 中直接使用數(shù)據(jù),這樣就可以避開(kāi) redirecting 的 300ms ~ 400ms了。如下圖:

渲染view線(xiàn)程和AppServcie是相互獨(dú)立的,對(duì)于AppServcie中js運(yùn)行不會(huì)阻塞view的渲染

官方的示例也是采用這種方式: 先App中請(qǐng)求數(shù)據(jù),在index.js使用數(shù)據(jù)

具體可以參考這篇文檔( https://mp.weixin.qq.com/s/EvzQoSwWYUmShtI_MkrFuQ ) 

有錯(cuò)誤的地方歡迎指出,共同進(jìn)步

最后遇到相關(guān)問(wèn)題開(kāi)發(fā)者社區(qū)搜索問(wèn)題



易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開(kāi)源 碼云倉(cāng)庫(kù):starfork
本文地址:http://22321a.com/wxmini/doc/course/24451.html 復(fù)制鏈接 如需定制請(qǐng)聯(lián)系易優(yōu)客服咨詢(xún):800182392 點(diǎn)擊咨詢(xún)
QQ在線(xiàn)咨詢(xún)