在前端越來(lái)越火的年代拐迁,逐漸衍生出類似React Native、Weex等開發(fā)套件疗绣。所達(dá)到的目的挺簡(jiǎn)單的线召,達(dá)到在多個(gè)平臺(tái)下共用一份代碼,節(jié)省開發(fā)成本多矮,提高開發(fā)效率缓淹。其次,由于JavaScript語(yǔ)言的特殊性塔逃,能動(dòng)態(tài)更新頁(yè)面而不需要發(fā)版讯壶。基于這兩點(diǎn)湾盗,越來(lái)越多的個(gè)人開發(fā)者&公司開始嘗試它們伏蚊。
本文將從個(gè)人開發(fā)實(shí)踐項(xiàng)目出發(fā),發(fā)表一些對(duì)于Weex的看法和在項(xiàng)目中的實(shí)戰(zhàn)經(jīng)歷格粪。不涉及具體原理和概念性的東西躏吊,讀者可以自行去Weex官網(wǎng)查閱。
Weex原理
大體上和React Native一致匀借,都是一個(gè)“放大版”的JSBrdige颜阐。其核心無(wú)非就是自定義了一套DSL(.we),配合vue實(shí)現(xiàn)數(shù)據(jù)綁定、vdom等等功能韵吨。再通過(guò)native端與JS端的數(shù)據(jù)魁蒜、API交互使得最終體現(xiàn)為native的調(diào)用過(guò)程。
而在這過(guò)程中资铡,iOS用了自帶的引擎JavaScriptCore & Android則是Google V8。在這過(guò)程中有個(gè)坑,iOS版本W(wǎng)eex有內(nèi)存泄漏的情況(Android沒有)均蜜,原因是JS Framework(Weex JS端的主程)并沒有像V8一樣hidden class的行為,GC回收不是很及時(shí)芒率。Weex開發(fā)團(tuán)隊(duì)的同事發(fā)現(xiàn)了此bug囤耳,并在后續(xù)的版本中修復(fù)。
OK偶芍,我認(rèn)為對(duì)于“應(yīng)用框架者”來(lái)說(shuō)充择,不用去care具體實(shí)現(xiàn)的原理。只需要了解怎么使用即可匪蟀,畢竟這只是一個(gè)工具椎麦。如果是為了學(xué)習(xí),可以去閱讀材彪,而對(duì)于“使用者”來(lái)說(shuō)观挎,快速地入門則是王道琴儿。
而Weex的使用,對(duì)于native來(lái)說(shuō)嘁捷,無(wú)非就是針對(duì)具體的業(yè)務(wù)場(chǎng)景實(shí)現(xiàn)Handler造成、Module、Component雄嚣。
Handler
我們可以把Weex看做是一個(gè)提供了基礎(chǔ)套件的UI渲染庫(kù)谜疤。核心功能還是需要開發(fā)者自己來(lái)實(shí)現(xiàn),比如:圖片下載邏輯现诀、網(wǎng)絡(luò)請(qǐng)求夷磕、導(dǎo)航跳轉(zhuǎn)等等。
所以開發(fā)者首先要關(guān)注的就是需要靜態(tài)分析自己當(dāng)前工程所需的功能仔沿,看看Weex需要你實(shí)現(xiàn)的handler中有哪些你要用到的坐桩,并實(shí)現(xiàn)它們。
比如在我的項(xiàng)目中封锉,就需要實(shí)現(xiàn)圖片下載邏輯绵跷,于是實(shí)現(xiàn)并注冊(cè)。
[WXSDKEngine registerHandler:[CNCWeexImageLoaderImplement new] withProtocol:@protocol(WXImgLoaderProtocol)];
Module
Module可以理解為JS端需要調(diào)用native才能處理的邏輯成福,并且在JS<->native進(jìn)行交互碾局。這么說(shuō)有點(diǎn)抽象,舉個(gè)具體的例子:比如在JS端想訪問(wèn)native端的數(shù)據(jù)庫(kù)(coredata奴艾、realm等)净当,就需要實(shí)現(xiàn)一個(gè)module來(lái)滿足JS調(diào)用native寫好的module以實(shí)現(xiàn)native的邏輯。
在我的實(shí)戰(zhàn)項(xiàng)目中蕴潦,選擇用module的方式實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求與導(dǎo)航跳轉(zhuǎn)像啼。
[WXSDKEngine registerModule:@"urlRoute" withClass:[CNCWeexURLRouteModule class]];
[WXSDKEngine registerModule:@"networkRequest" withClass:[CNCWeexURLRouteModule class]];
Component
Component很好理解,要實(shí)現(xiàn)一個(gè)跑馬燈UI的效果潭苞,在native端實(shí)現(xiàn)忽冻,并且注冊(cè)到JS。JS端調(diào)用此疹,即可展示出跑馬燈僧诚。這就是Component,在JS滿足不了或者實(shí)現(xiàn)成本很高的時(shí)候蝗碎,則可以在native端實(shí)現(xiàn)Component供JS調(diào)用湖笨。
由于第一次試水Weex,并沒有采取很復(fù)雜的UI衍菱,就沒有用Component赶么。
踩過(guò)的坑
JS中this關(guān)鍵字的用法與Objc不同,this的作用域僅在當(dāng)前對(duì)象脊串。而在JS中函數(shù)也算一個(gè)對(duì)象辫呻。如果在函數(shù)中套一個(gè)函數(shù)清钥,此時(shí)用this,只能代表外層函數(shù)放闺。而非Objc一樣代表整個(gè)最外層對(duì)象祟昭,需要注意!
業(yè)務(wù)中碰到一個(gè)場(chǎng)景怖侦,需要在某個(gè)場(chǎng)景篡悟,native端主動(dòng)調(diào)用JS。而Weex提供給外部的API并沒有提供這樣的能力匾寝,僅僅是在JS主動(dòng)調(diào)native方法時(shí)傳一個(gè)callback搬葬,并且在native方法執(zhí)行完成時(shí),callback銷毀艳悔。而業(yè)務(wù)場(chǎng)景卻需要在將來(lái)執(zhí)行回傳下來(lái)的callback急凰。翻看源碼,只能自己實(shí)現(xiàn)了猜年。這里給個(gè)思路:
其實(shí)在Weex的實(shí)現(xiàn)中(不貼源碼了)抡锈,會(huì)判斷native實(shí)現(xiàn)的方法(即給JS調(diào)用的方法,比如module實(shí)現(xiàn)的方法)的入?yún)㈩愋颓峭狻H绻锹暶鞒蒞XModuleCallback床三,則Weex內(nèi)部會(huì)進(jìn)行處理,并轉(zhuǎn)成block給iOS(Android同理)杨幼。而如果不是WXModuleCallback撇簿,則會(huì)透?jìng)饕粋€(gè)String(weex標(biāo)記的方法ID)下來(lái),這很關(guān)鍵推汽。于是我們可以投機(jī)取巧地把入?yún)⒏某蒘tring补疑,記錄下這個(gè)String歧沪。在后期想調(diào)這個(gè)JS方法時(shí)歹撒,寫如下代碼即可
[[WXSDKManager bridgeMgr] callBack:weexInstance.instanceId funcId:aliveCallBackID params:params keepAlive:YES];
看法
Weex相比React Native,坑還是比較多的诊胞。但是從“使用者”角度來(lái)說(shuō)暖夭,Weex方便很多。但是對(duì)于存在很多復(fù)雜業(yè)務(wù)場(chǎng)景的開發(fā)者來(lái)說(shuō)撵孤,必然會(huì)去學(xué)習(xí)其原理迈着,而此時(shí)Weex相比RN就沒那么友善了。
因?yàn)樵诎⒗镄奥耄腋又С諻eex裕菠,也希望它變得越來(lái)越好。
無(wú)論采用哪種方式闭专,兩者都能實(shí)現(xiàn)客戶端的動(dòng)態(tài)化奴潘。而這對(duì)于一些多變的頁(yè)面來(lái)說(shuō)旧烧,是一種新的選擇方式。
這是客戶端動(dòng)態(tài)化系列的第二篇文章画髓,讀者可以看前篇客戶端動(dòng)態(tài)化系列之——URLRoute掘剪,相信你對(duì)動(dòng)態(tài)化有更深的理解。