以前介紹的WXML、WXSS、JS、WXS都是運行在MINA框架上。html
MINA的核心是一個響應的數據綁定系統。整個系統分爲兩塊:視圖層(View) 和 邏輯層(App Service)。MINA可讓數據與視圖保持同步很是簡單。當作數據修改的時候,只須要在邏輯層修改數據,視圖層就會作相應的更新。json
框架原理圖以下:小程序
View視圖層:wxml是MINA提供的一套相似html標籤的語言以及一系列基礎組件。開發者使用wxml文件來搭建頁面的基礎視圖結構,使用wxss文件來控制頁面的展示樣式。緩存
AppService應用邏輯層:MINA的服務中心,由微信客戶端啓用異步線程單獨加載運行。頁面渲染所需的數據、頁面交互處理邏輯都在AppService中實現。MINA框架中的AppService使用JavaScript來編寫交互邏輯、網絡請求、數據處理,但不能使用JavaScript中的DOM操做。小程序中的各個頁面能夠經過AppService實現數據管理、網絡通訊、應用生命週期管理和頁面路由。Mananger用於處理事件邏輯和事件處理,API向外提供了應用接口。服務器
MINA框架爲頁面組件提供了bindtap、bindtouchstart等事件監聽相關的屬性,來與AppService中的事件處理函數綁定在一塊兒,實現也面向AppService層同步用戶交互數據。MINA框架同時提供了不少方法將AppService中的數據與頁面進行單向綁定,當AppService中的數據變動時,會主動觸發對應頁面組件的從新渲染。MINA使用virtualdom技術,加快了頁面的渲染效率。微信
分爲熱啓動和冷啓動。網絡
小程序啓動的時候會從CDN服務器上加載小程序代碼包,並緩存到微信後臺,下載完成後啓動小程序。若是本地已經緩存小程序代碼包,每次啓動小程序,微信會從CDN上查詢是否有新版本的代碼包,若是有,則在後臺下載,下次啓動的時候啓用新版小程序。併發
小程序經過AJAX嚮應用服務器發起請求,應用服務器返回JSON格式的數據。app
App() 函數用來註冊一個小程序。接受一個 object 參數,其指定小程序的生命週期函數等。object參數說明:框架
屬性 |
類型 |
描述 |
觸發時機 |
onLaunch |
Function |
生命週期函數--監聽小程序初始化 |
當小程序初始化完成時,會觸發 onLaunch(全局只觸發一次) |
onShow |
Function |
生命週期函數--監聽小程序顯示 |
當小程序啓動,或從後臺進入前臺顯示,會觸發 onShow |
onHide |
Function |
生命週期函數--監聽小程序隱藏 |
當小程序從前臺進入後臺,會觸發 onHide |
onError |
Function |
生命週期函數--監聽小程序錯誤信息 |
當小程序調用API失敗時候會調用onError鉤子,並傳入錯誤信息。 |
前臺、後臺定義: 當用戶點擊左上角關閉,或者按了設備 Home 鍵離開微信,小程序並無直接銷燬,而是進入了後臺;當再次進入微信或再次打開小程序,又會從後臺進入前臺。
示意圖:
globalData表示小程序全局數據。
示例代碼:
App({ onLaunch: function () { console.log("小程序初始化"); }, onShow: function () { console.log("小程序進入前臺"); }, onHide: function () { console.log("小程序進入後臺"); }, onError: function (msg) { console.log(msg) }, globalData: '全局數據' }) |
小程序提供了全局的 getApp()函數,能夠獲取到小程序實例。
示例代碼:
// other.js var appInstance = getApp() console.log(appInstance.globalData) // I am global data |
注意:
Page()函數用來註冊一個頁面。接受一個 object 參數,其指定頁面的初始數據、生命週期函數、事件處理函數等。
object 參數說明:
注意:
onLoad: 頁面加載。
onShow: 頁面顯示
onReady: 頁面初次渲染完成
onHide: 頁面隱藏
onUnload: 頁面卸載
由上圖可知,小程序由兩大線程組成:負責界面的視圖線程(view thread)和負責數據、服務處理的服務線程(appservice thread),二者協同工做,完成小程序頁面生命週期的調用。
視圖線程有四大狀態:
服務線程五大狀態:
在小程序中全部頁面的路由所有由框架進行管理。
對於路由的觸發方式以及頁面生命週期函數以下:
注意:
(以 A、B 頁面爲 Tabbar 頁面,C 是從 A 頁面打開的頁面,D 頁面是從 C 頁面打開的頁面爲例):
視圖代碼:
<!--index.wxml--> <view> <view class='btn' bindtap='clickme'>點擊我 </view> </view> |
樣式代碼:
/**index.wxss**/ .btn{ width: 100px; height: 30px; text-align: center; border: 1px solid black; line-height: 30px; margin: 100px auto; } |
邏輯層處理代碼:
//index.js Page({ //點擊事件處理函數 clickme: function(e) { console.log(e); } }) |
控制檯輸出:
事件屬性說明:
Tap:觸發事件類型。
changedTouches:表示有變化的觸摸點,如從無變有(touchstart),位置變化(touchmove),從有變無(touchend、touchcancel)。
currentTarget:事件綁定的當前組件。
Target:觸發事件的源組件。
detail:自定義事件所攜帶的數據,如表單組件的提交事件會攜帶用戶的輸入,媒體的錯誤事件會攜帶錯誤信息,詳見組件定義中各個事件的定義。點擊事件的detail 帶有的 x, y 同 pageX, pageY 表明距離文檔左上角的距離。
和JavaScript的事件模型相似
tap表示按壓屏幕小於350ms。
longpress:按壓時間超過350ms的事件操做,不會再觸發tap操做。(長按操做推薦)
longtap:觸發以後會繼續觸發tap操做。
樣式文件:
/* pages/index/index.wxss */ #outter{ border: 1px red solid; background-color: red; width: 80%; height: 200px; margin: 100px auto; text-align: center; }
#middle{ border: 1px white solid; background-color: white; width: 80%; height: 120px; margin: 20px auto; }
#inner{ border: 1px yellow solid; background-color: yellow; width: 80%; height: 50px; margin: 10px auto; } |
事件回調函數定義:
// pages/index/index.js Page({ click1() { console.log("冒泡:點擊了C1"); }, click2() { console.log("冒泡:點擊了C2"); }, click3() { console.log("冒泡:點擊了C3"); }, click11() { console.log("捕獲:點擊了C1"); }, click22() { console.log("捕獲:點擊了C2"); }, click33() { console.log("捕獲:點擊了C3"); } }) |
視圖層代碼:
<!--pages/index/index.wxml--> <view id="outter" bindtap='click1' capture-bind:tap="click11"> 外層容器C1 <view id="middle" bindtap='click2' capture-bind:tap="click22"> 中間層容器C2 <view id="inner" bindtap='click3' capture-bind:tap="click33"> 內層容器C3 </view> </view> </view> |
點擊C1,測試結果:
分別點擊C三、C二、C1,測試結果:
注意:
<!--pages/index/index.wxml--> <view id="outter" bindtap='click1' capture-bind:tap="click11"> 外層容器C1 <view id="middle" bindtap='click2' capture-bind:tap="click22"> 中間層容器C2 <view id="inner" bindtap='click3' capture-catch:tap="click33"> 內層容器C3 </view> </view> </view> |
測試效果,點擊C3容器: