摘要:傳輸時間與數(shù)據(jù)量大體上呈現(xiàn)正相關(guān)關(guān)系,傳輸過大的數(shù)據(jù)將使這一時間顯著增加。小程序不管從組件化開發(fā)調(diào)試發(fā)布灰度回滾上報統(tǒng)計(jì)監(jiān)控和最近的云能力都非常完善,小程序的工程化簡直就是前端的典范。
研究背景
上一篇文章了解了小程序的生命周期,接下來研究一下數(shù)據(jù)通信,我覺得清楚了生命周期和數(shù)據(jù)通信,就能對整個程序有一定的把控能力,定位問題和解決問題的能力將大幅提高天生的延時
我剛開始擼小程序的時候,覺得看看文檔就可以了,導(dǎo)致寫了很多垃圾代碼坑人坑己,相信大部分初學(xué)者也不會去仔細(xì)研究文檔,更別說啰里啰嗦的指南了,在通讀小程序官方指南后,我覺得很有必要為初學(xué)者總結(jié)一番,教學(xué)相長
為了解決管控與安全問題,小程序提供了一個沙箱環(huán)境來運(yùn)行開發(fā)者的JavaScript 代碼
基于雙線程模型,意味著任何數(shù)據(jù)傳遞都是線程間的通信
在小程序架構(gòu)里,這一切都會變成異步
異步會使得各部分的運(yùn)行時序變得復(fù)雜一些,因此邏輯層與渲染層需要有一定的機(jī)制保證時序正確
這些工作在小程序框架里會處理好,開發(fā)者只需要理解生命周期,以及控制合適的時機(jī)更新UI即可
上一篇文章我們學(xué)習(xí)了小程序的生命周期,本文主要理解如何控制合適的時機(jī)更新UI
如何控制合適的時機(jī)更新UI小程序作為MVVM框架中的一員,數(shù)據(jù)驅(qū)動是核心,得數(shù)據(jù)者得天下
要理解數(shù)據(jù)通信,和生命周期、運(yùn)行機(jī)制密不可分,像雙線程通信模型、數(shù)據(jù)驅(qū)動、底層框架、界面渲染機(jī)制等等,本文不會展開敘述,也不可能講的比官方文檔更好、更實(shí)時
本文主要理解以下幾點(diǎn):(想了半天,才概括如下)
1、小程序中數(shù)據(jù)的作用域
2、合理操作數(shù)據(jù),提升性能
3、組件間的數(shù)據(jù)通信
4、緩存數(shù)據(jù)
5、擴(kuò)展-狀態(tài)管理westore
在這之前,還是上幾張官方的圖,有個概念便于后續(xù)理解
明確幾點(diǎn)概念
渲染層和數(shù)據(jù)相關(guān)
邏輯層負(fù)責(zé)產(chǎn)生、處理數(shù)據(jù),小程序的JS腳本運(yùn)行在同一個JsCore線程里
邏輯層和渲染層是一對多的關(guān)系,但頁面對象(page)和頁面層級(webview)一一對應(yīng)
一、小程序中數(shù)據(jù)的作用域 1、全局?jǐn)?shù)據(jù)// app.js App({ globalData: "I am global data" // 全局共享數(shù)據(jù) }) // 其他頁面腳本other.js var appInstance = getApp() console.log(appInstance.globalData) // 輸出: I am global data
App實(shí)例是單例的,因此不同頁面直接可以通過App實(shí)例下的屬性來共享數(shù)據(jù)
2、頁面共享數(shù)據(jù)簡單來說就是頁面所在的JS中Page構(gòu)造器外定義的變量
執(zhí)行如下示例代碼以驗(yàn)證
console.log("加載 page.js") var count = 0 Page({ onLoad: function() { count += 1 console.log("第 " + count + " 次啟動這個頁面") } })
你會發(fā)現(xiàn)小程序啟動時,打印了"加載 page.js",每次打開這個頁面,count變量會遞增,不會隨著頁面的銷毀而銷毀
由于頁面所在的JS文件、app.js和所有其他被require的JS文件,在小程序啟動時自動執(zhí)行并被基礎(chǔ)庫注冊,所以邏輯層(看作所有js的集合)只執(zhí)行一次,之后都是通過Page構(gòu)造器創(chuàng)建Page實(shí)例來渲染頁面
一般require的依賴或者第三方庫JS以及getApp(),我們都會放在頁面共享的數(shù)據(jù)中
3、Page實(shí)例中的數(shù)據(jù)也就是每個Page構(gòu)造器中的數(shù)據(jù),沒錯!這就是我們每天搬磚的地方
Page({ data: { text: "我用來改變界面顯示" }, onLoad: function(options) { }, onReady: function() { }, onShow: function() { }, onHide: function() { }, onUnload: function() { }, text: "我不顯示在頁面上", myData:{ a: "我也不顯示在頁面上", b: true } })
大家應(yīng)該都知道data中的數(shù)據(jù)用來渲染頁面,和VUE一樣,不過VUE中只要寫this.text,而小程序中要寫this.data.text,每次寫到這個就郁悶,其實(shí)與界面渲染無關(guān)的數(shù)據(jù)最好不要設(shè)置在data中,對性能也是大有好處
4、自定義組件中的數(shù)據(jù)properties外部傳值
data內(nèi)部數(shù)據(jù)
emmmmmm自定義組件有必要另開一篇總結(jié)
二、合理操作數(shù)據(jù),提升性能 數(shù)據(jù)通信頁面初始數(shù)據(jù)通信:視圖層在接收到初始數(shù)據(jù)data時,進(jìn)行初始渲染
更新數(shù)據(jù)通信:視圖層在接收到更新數(shù)據(jù)setData時,進(jìn)行重渲染
用戶事件通信:一個用戶事件被觸發(fā),視圖層會將信息反饋給邏輯層
一切都是2個線程通信的結(jié)果,數(shù)據(jù)量小于64KB時總時長可以控制在30ms內(nèi)。傳輸時間與數(shù)據(jù)量大體上呈現(xiàn)正相關(guān)關(guān)系,傳輸過大的數(shù)據(jù)將使這一時間顯著增加。因而減少傳輸數(shù)據(jù)量是降低數(shù)據(jù)傳輸時間的有效方式
提升性能須遵循的原則調(diào)用setData執(zhí)行重渲染時,視圖層將data和setData數(shù)據(jù)套用在WXML片段上,得到一個新節(jié)點(diǎn)樹,然后與當(dāng)前節(jié)點(diǎn)樹進(jìn)行比較,這樣可以得到哪些節(jié)點(diǎn)的哪些屬性需要更新、哪些節(jié)點(diǎn)需要添加或移除,最后,將setData數(shù)據(jù)合并到data中,并用新節(jié)點(diǎn)樹替換舊節(jié)點(diǎn)樹,用于下一次重渲染。
可以看出邏輯層setData發(fā)送數(shù)據(jù)給更新視圖時,需要兩個線程的一些通信消耗,且不會diff數(shù)據(jù),只會一股腦傳過去,生成新節(jié)點(diǎn)樹,每一次通信都需要經(jīng)過傳輸、生成、比較、合并
為了提升數(shù)據(jù)更新的性能,最好遵循以下原則:
1、不要過于頻繁調(diào)用setData,應(yīng)考慮將多次setData合并成一次setData調(diào)用
2、數(shù)據(jù)通信的性能與數(shù)據(jù)量正相關(guān),每次只設(shè)置需要改變的最小單位數(shù)據(jù)
3、與界面渲染無關(guān)的數(shù)據(jù)最好不要設(shè)置在data中,可以考慮設(shè)置在page對象的其他字段下
其他優(yōu)化策略:
1、去掉不必要的事件綁定(WXML中的bind和catch),從而減少通信的數(shù)據(jù)量和次數(shù)
2、事件綁定時需要傳輸target和currentTarget的dataset,因而不要在節(jié)點(diǎn)的data前綴屬性中放置過大的數(shù)據(jù)
3、精簡代碼,降低WXML結(jié)構(gòu)和JS代碼的復(fù)雜性,必要時使用分包優(yōu)化
注意:
直接修改 Page實(shí)例的this.data 而不調(diào)用 this.setData 是無法改變頁面的狀態(tài)的,還會造成數(shù)據(jù)不一致
不要把data中的任意一項(xiàng)的value設(shè)為undefined,否則可能會有引起一些不可預(yù)料的bug
三、組件間的數(shù)據(jù)通信 組件區(qū)分業(yè)務(wù)組件和純組件業(yè)務(wù)組件與業(yè)務(wù)數(shù)據(jù)緊耦合,換一個項(xiàng)目可能該組件就用不上,除非非常類似的項(xiàng)目
業(yè)務(wù)組件和頁面一樣通過 全局變量 獲得所需參數(shù),通過更改 全局變量 與外界通訊
業(yè)務(wù)組件也可以通過 props 獲得所需參數(shù),通過 triggerEvent 與外界通訊
純組件與業(yè)務(wù)數(shù)據(jù)無關(guān),可移植和復(fù)用
純組件只能通過 props 獲得所需參數(shù),通過 triggerEvent 與外界通訊
四、緩存數(shù)據(jù)本地數(shù)據(jù)緩存是小程序存儲在當(dāng)前設(shè)備上硬盤上的數(shù)據(jù),小程序宿主環(huán)境從不同小程序和不同用戶兩個維度來隔離緩存空間,每個小程序的緩存空間上限為10MB
緩存充當(dāng)全局?jǐn)?shù)據(jù)
通過wx.getStorage/wx.getStorageSync讀取本地緩存
通過wx.setStorage/wx.setStorageSync寫數(shù)據(jù)到緩存
利用本地緩存提前渲染界面
我們在拉取商品列表后把列表存在本地緩存里
在onLoad發(fā)起請求前,先檢查是否有緩存過列表
如果有的話直接渲染界面
等到wx.request的success回調(diào)之后再覆蓋本地緩存重新渲染新的列表
Page({ onLoad: function() { var that = this var list =wx.getStorageSync("list") if (list) { // 本地如果有緩存列表,提前渲染 that.setData({ list: list }) } wx.request({ url: "https://test.com/getproductlist", success: function (res) { if (res.statusCode === 200) { list = res.data.list that.setData({ // 再次渲染列表 list: list }) wx.setStorageSync("list",list) // 覆蓋緩存數(shù)據(jù) } } }) } })
一般在對數(shù)據(jù)實(shí)時性/一致性要求不高的頁面采用這個方法來做提前渲染,用以優(yōu)化小程序體驗(yàn)
五、擴(kuò)展-狀態(tài)管理westore引用
眾所周知,小程序通過頁面或組件各自的 setData 再加上各種父子、祖孫、姐弟、姑姑與堂兄等等組件間的通訊會把程序搞成一團(tuán)漿糊,如果再加上跨頁面之間的組件通訊,會讓程序非常難維護(hù)和調(diào)試。雖然市面上出現(xiàn)了許多技術(shù)棧編譯轉(zhuǎn)小程序的技術(shù),但是我覺沒有戳中小程序的痛點(diǎn)。小程序不管從組件化、開發(fā)、調(diào)試、發(fā)布、灰度、回滾、上報、統(tǒng)計(jì)、監(jiān)控和最近的云能力都非常完善,小程序的工程化簡直就是前端的典范。而開發(fā)者工具也在持續(xù)更新,可以想象的未來,組件布局的話未必需要寫代碼了。而且據(jù)統(tǒng)計(jì),開發(fā)小程序使用最多的技術(shù)棧是使用小程序本身的開發(fā)工具和語法,所以最大的痛點(diǎn)只剩下狀態(tài)管理和跨頁通訊
現(xiàn)在主流的MVVM框架如vue/react/angluar都有狀態(tài)管理,小程序也可以有,由于小程序的即時特性,迭代更新非常快,所以對于小程序我是崇尚原生開發(fā)的,不過多端合一也是很nice的解決方案,自己玩的時候當(dāng)然要試試dcloud公司的uniapp
廢話不多說,直接貼圖和鏈接,有興趣的自行研究哈,Westore 的方案:
Westore項(xiàng)目地址
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/101390.html
摘要:運(yùn)行機(jī)制小程序啟動會有兩種情況,一種是冷啟動,一種是熱啟動。建議小程序在必要時使用監(jiān)聽內(nèi)存告警事件,進(jìn)行必要的內(nèi)存清理。 前言 以小程序?yàn)榍腥朦c(diǎn),深入理解總結(jié)方方面面的知識點(diǎn),做成系列文章,希望能得到大神的指點(diǎn)和幫助新人入門,承上啟下才是好程序猿由于是系列第一篇文章,緊跟著的是一大段廢話,只關(guān)心技術(shù)的可以跳過 轉(zhuǎn)眼半年又要過去了,意味著來新公司快半年了,離上次寫文章也半年了,渾渾噩噩...
摘要:大多數(shù)待遇豐厚的開發(fā)職位都要求開發(fā)者精通多線程技術(shù)并且有豐富的程序開發(fā)調(diào)試優(yōu)化經(jīng)驗(yàn),所以線程相關(guān)的問題在面試中經(jīng)常會被提到。將對象編碼為字節(jié)流稱之為序列化,反之將字節(jié)流重建成對象稱之為反序列化。 JVM 內(nèi)存溢出實(shí)例 - 實(shí)戰(zhàn) JVM(二) 介紹 JVM 內(nèi)存溢出產(chǎn)生情況分析 Java - 注解詳解 詳細(xì)介紹 Java 注解的使用,有利于學(xué)習(xí)編譯時注解 Java 程序員快速上手 Kot...
面試舊敵之紅黑樹(直白介紹深入理解) - Android - 掘金 讀完本文你將了解到: 什么是紅黑樹 黑色高度 紅黑樹的 5 個特性 紅黑樹的左旋右旋 指定節(jié)點(diǎn) x 的左旋 右圖轉(zhuǎn)成左圖 指定節(jié)點(diǎn) y 的右旋左圖轉(zhuǎn)成右圖 紅黑樹的平衡插入 二叉查找樹的插入 插入后調(diào)整紅黑樹結(jié)構(gòu) 調(diào)整思想 插入染紅后... java 多線程同步以及線程間通信詳解 & 消費(fèi)者生產(chǎn)者模式 & 死鎖 & Thread...
閱讀 1863·2023-04-26 02:46
閱讀 1995·2021-11-25 09:43
閱讀 1140·2021-09-29 09:35
閱讀 2095·2019-08-30 15:56
閱讀 3418·2019-08-30 15:54
閱讀 2627·2019-08-29 16:35
閱讀 3116·2019-08-29 15:25
閱讀 3282·2019-08-29 14:01