Weex原理之帶你去蹲坑

?本篇將節(jié)操滿滿的安利Weex(? ̄? ??  ̄??)设拟,不一樣的角度推薦你入坑,官網(wǎng)有的我們不拖泥悬嗓,這里將給你補充官方?jīng)]有的,深入到蹲坑給你排憂解難裕坊,總會給你點驚喜,內(nèi)容越后越干燕酷,請緊張的往下看籍凝。

兩個字,講究

***** 本文配套苗缩,超完整 Weex 項目推薦 : GSYGithubAppWeex *****

一饵蒂、簡介

?有對比才有傷害,說到Weex酱讶,難免讓人聯(lián)系React Native退盯。雖同為跨平臺移動端解決方案,擁JavaScript妄一統(tǒng)天下泻肯,單兩者的設(shè)計理念其實截然不同渊迁。

?這里先介紹下兩者的差異,給徘徊在 React Native 和 Weex 之間的人灶挟,理解更適合哪些場景琉朽。

類型 React Native Weex
性能 較好 較弱
上手難度 稍高 容易
核心理念 React Vue
框架程度 較重 較輕
特點 適合開發(fā)整體App 適合單頁面
社區(qū) 豐富,F(xiàn)acebook維護 略殘念稚铣,目前托管apache
支持 Android箱叁、IOS Android墅垮、IOS、Web
適應(yīng)性 原生開學(xué)習(xí)成本低 Web開發(fā)學(xué)習(xí)成本低
JS引擎 JSCore V8

?作為兩個框架的深度體驗者耕漱,個人總結(jié)出上面的對比算色,其中可以看出:

  • React Native更適合開發(fā)完整的App,因為它的性能較好螟够,第三方插件豐富灾梦,社群活躍并且維護較好,文檔完整等(本篇主角是Weex好吧魂淡(#?Д?))齐鲤。

  • Weex更適合開發(fā)單頁面集成斥废,這也是阿里的業(yè)務(wù)特性。
    當然Weex也可以開發(fā)完整的多頁面App给郊,同時我也是這么用過牡肉,不過效果對比React Native,顯然強差人意淆九。

  • Weex勝在容易上手统锤,基于Vue的設(shè)計模式,類MVVM的實現(xiàn)炭庙,也讓前端能更無縫的實現(xiàn)一些高性能的App業(yè)務(wù)饲窿。

  • Weex兼容Android、IOS焕蹄、Web三端逾雄,在單頁面的實現(xiàn)上,它有著React Native無法睥睨的先天優(yōu)勢腻脏。

  • Weex的社群鸦泳,個人覺得還是弱,資料不足永品,文檔簡單做鹰,第三方支持太弱。和React Native一樣支持帶原生功能的插件開發(fā)鼎姐,但是钾麸,支持太少了,這也提高了后期的開發(fā)門檻炕桨。同時饭尝,一個小問題很容易讓入初學(xué)者,三過門而不入谋作,作為一個發(fā)布了兩年的框架芋肠,還是比較讓人吐槽的。

這就是遵蚜,所謂的前言吧

二帖池、原理

?這里簡要說明下Weex在android下的分層以及原理奈惑。

?Weex主要包括三大部分:JS BridgeRender睡汹、Dom肴甸,分別對應(yīng)WXBridgeManagerWXRenderManager囚巴、WXDomManager 原在。通過WXSDKManager統(tǒng)一管理。其中JS BridgeDom運行在獨立的HandlerThread中彤叉,而Render運行在UI線程庶柿。JS Bridge主要用來和 JS 端實現(xiàn)進行雙向通信,比如把js端的dom結(jié)構(gòu)傳遞給Dom線程秽浇。Dom主要是用于負責dom的解析浮庐、映射、添加等等的操作柬焕,最后通知UI線程更新审残。而Render負責在UI線程中對dom實現(xiàn)渲染。

?如下圖斑举,是生成dom搅轿,dom的解析,映射富玷,添加璧坟,渲染的流程。

圖片來自網(wǎng)絡(luò)

?如上可知赎懦,因為JS端運行于獨立的單線程中沸柔,所以為了保證運行的流暢性,一般需要避免在JS端執(zhí)行耗時操作铲敛,比如:網(wǎng)絡(luò)請求,圖片加載等会钝,其實都是在原生端完成伐蒋,js端執(zhí)行的是發(fā)起一個請求和響應(yīng)一個結(jié)果。同時因為原生端與JS端是通過JS Bridge通訊迁酸,所以也需要盡量避免大數(shù)據(jù)和頻繁的通訊先鱼,導(dǎo)致響應(yīng)的延遲。

?原生端的dom的加載解析映射奸鬓,也是性能的一大瓶頸焙畔。一般而言,Weex在Web端生成的串远,是通過webpack的webConfig打包成單頁面的index.web.js文件宏多;而在原生端儿惫,一般會通過webpack的weexEntry配置成多頁面形式:即每一個需要獨立的.vue的頁面,最終會被打包成一個.js文件伸但。所以打開每個頁面時加載對應(yīng)的js文件肾请,這很好的減小了需要加載的文件大小,提高了dom的解析效率更胖。最后铛铁,Weex默認打的js只包含業(yè)務(wù)js代碼,基礎(chǔ)js庫已經(jīng)被包含在weex sdk中却妨,也使得體積會小很多饵逐。

三、入門

1彪标、配置環(huán)境

?程序員就要從配置環(huán)開始倍权,Weex 環(huán)境搭建 ,點擊鏈接捐下,只要你要一個穩(wěn)定的網(wǎng)絡(luò)账锹,參考官網(wǎng)搭建環(huán)境,也就一杯茶的功夫坷襟,take it easy奸柬。配置好之后,weex create testProject創(chuàng)建一個項目High起來吧婴程。

2廓奕、快速入門

?weex的入門還是比較簡單的,JavaScript档叔、Vue了解下桌粉,即可預(yù)約的hello world。

?原生開發(fā)也許對vue接觸不多衙四,跨界有時候很容易望而卻步铃肯,其實Vue本身,就是容易上手的框架传蹈,類似MVVM的模式(類似Android的DataBinding)押逼,很容讓人理解上手,簡單的說惦界,你只關(guān)心數(shù)據(jù)挑格,然后綁定到顯示的控件,就是這么簡單沾歪。

?一般通過 Vue官網(wǎng) 教程漂彤,30分快速擼一發(fā),之后你就直接入門Weex了,對挫望,Weex做的最徹底的就是立润,你直接使用 vue 寫一個Web頁面,之后再順手編譯成了 ios 和 android 的原生頁面(盡管有些時候你需要在平臺適配上花費心思)士骤。

請忽略那個this范删,真的( ̄. ̄)

?如上圖(請忽略那個this( ̄. ̄))譬巫,這就是一個極度簡化的宙橱,用Vue寫的Weex頁面。效果是從顯示Hello World 球散,一秒變I’m CarGuo巨缘,就是這么自信添忘。

?在<template>中排布需要渲染的控件,在<style>中指定控件的樣式(當然你也可以直接在<template>中)若锁,在<script>中寫數(shù)據(jù)獲取和處理邏輯等搁骑,是不是很簡單, Don’t be shy又固,Let's fuck it 仲器!

?因為需要支持三端,Weex在Vue的基礎(chǔ)上閹割了一些標簽仰冠、css樣式和事件乏冀,具體可見與 Web 平臺的差異

?其中,在Android和IOS上洋只,<text> <image>等標簽辆沦,其實是被編譯為原生控件,這就是上面所說的dom解析识虚,同時你也可以在原生端肢扯,自定義控件或者功能模塊,然后注冊到weex中使用担锤,實際上weex提供的基礎(chǔ)控件和功能模塊并不多蔚晨,但卻很容易拓展,具體可見 拓展原生端功能 肛循。

(ps 也不知道阿里是怕做多錯多蛛株,還是懶)

?說到這里,就需要說一說Weex的原生插件開發(fā)支持育拨,這也是官方文檔比較沒整理好的原因,其實文檔是有的:Weex插件開發(fā)文檔欢摄,如Android插件大致流程就是:

  • weex plugin create命令創(chuàng)建插件熬丧。
  • 在android目錄的library下通過@WeexComponent(控件)、@WeexModule(非UI功能)怀挠、@WeexAdapter(weex繼承功能拓展)實現(xiàn)第三方支持析蝴。
  • 將library發(fā)布到maven (當然你也可以直接源碼發(fā)布到npm)
  • 配置根目錄的package.json然后發(fā)布到npm

?由此可見害捕,weex可以很方便的提供原生功能的拓展支持,但是由于社群較為薄弱闷畸,導(dǎo)致第三方插件缺失尝盼,有(hen)些(duo)時候你可能不得不自己著手,開發(fā)原生端的功能支持佑菩,這就對于跨平臺開發(fā)而言盾沫,特別前端開發(fā)而言,就稍(te)顯(bie)不友好了殿漠。

目瞪狗帶

? 題外話 :說到跨平臺開發(fā)赴精,也許你聽說過cordova這位老大哥,它曾是早期的跨平臺開發(fā)潮流绞幌,cordova提供豐富的原生插件和打包功能:通過webview把前端頁面打包成一個App蕾哟,通過插件提供前端需要的原生接口,交互通過webview的js接口支持莲蜘。為什么說起它呢谭确,是因為Weex中,你可以看到很多cordova的影子票渠,類似weex platform add android逐哈、weex plugin add xxx都有些cordova的味道。如下圖庄新,你如今依舊可以在Weex中找鞠眉,尋找到cordova的存在感。

cordova殘留
3择诈、其他推薦
? Vuex 和 Vue-Router 械蹋,居家旅行必不可少。
  • Vuex類似Redux羞芍,如果你沒聽說Redux不要緊哗戈,也不要慫,簡單了說荷科,Vuex就是單頁面下唯咬,幫你管理數(shù)據(jù)的框架。數(shù)據(jù)都存在Vuex的store中畏浆,你操作store更新數(shù)據(jù)胆胰,然后將store綁定到界面。它的用處在于可以在多個vue組件間刻获,方便的同步數(shù)據(jù)蜀涨,更新界面。

  • Vue-Router也是用于單頁面下,指定跳到某個頁面的管理工具厚柳,路由嘛氧枣,淺顯易懂。

? iconfont :矢量圖標别垮,少不了iconfont便监,通過字庫生成圖標,資源豐富碳想,絕對值得推薦烧董。
? weex-ui: weex中難得的良心官方封裝庫。
? eros :eros 不是框架移袍,是基于 weex 封裝解藻、面向前端的 vue 寫法的一整套 APP 開源解決方案,是由本木醫(yī)療大前端團隊經(jīng)過大量實踐沉淀而出葡盗。螟左。

四、深入填坑

1觅够、ES6胶背、ES7

? 說到 Javascript ,ES6喘先、ES7必須了解下钳吟。Weex中默認就有對其支持,但是對于async窘拯、await等红且,還需要如下一些簡單配置,然后 have fun 涤姊。

//命令行安裝
npm install --save-dev babel-plugin-transform-runtime

//然后在.babelrc文件中加入
{
"presets": [
"es2015",
"stage-0"
],
"plugins": [ [
"transform-runtime",
{
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": "babel-runtime"
}
]]
}
2暇番、多頁面

?Weex默認是單頁面效果,也就是Android中一個Activity的概念思喊,而單頁面效果在原生上壁酬,跳轉(zhuǎn)一多效果就會web了。既然叫native恨课,怎么可能如此too young舆乔,所以這個時候,就需要修改默認的webpack剂公,讓其支持naive多頁面了?╮(╯▽╰)╭希俩。

?首先,要知道Weex真正運行的是纲辽,通過entry.js作為入口文件文件颜武,通過webpack贫母,將.vue文件打包成index.js進行使用。Look盒刚,多頁面的重點,就是將獨立頁面的.vue文件绿贞,生成多個js文件因块。

入口js

?如上圖,參考entry.js文件籍铁,創(chuàng)建一個SecondPageEntry.js涡上,作為SecondPage.vue的入口,用于webpack生成SecondPage.js頁面拒名。

?什么吩愧?webpack沒聽說過怎么辦,No problem增显,你只需簡單的修改雁佳,一知半解完全可以勝任。如下圖同云,我們主要需要修改webpack.common.conf.js文件糖权,

webpack.common.conf.js

?可以看出,webpack.common.conf.js中炸站,其實是區(qū)分了webConfig和weexConfig的不同打包方式星澳。如下圖,其中weexEntry就是我們需要修改的地方旱易,可以看到本來已經(jīng)有index和entry.js存在了禁偎。

?最后我們需要通過navigator來實現(xiàn)跳轉(zhuǎn),我們需要知道阀坏,要跳轉(zhuǎn)的js文件在哪里如暖,如下代碼演示,如何實現(xiàn)navigotor的native跳轉(zhuǎn)全释,完整兼容三端跳轉(zhuǎn)請移步demo項目装处。

 //獲取當前js文件所在完整路徑
 let bundleUrl = this.$getConfig().bundleUrl;
 bundleUrl = String(bundleUrl);
 let nativeBase;
 //android一般位于file://assets目錄下
 let isAndroidAssets = bundleUrl.indexOf('file://assets/') >= 0;
 //ios一般位于一般帶有file開頭,帶有WeexDemo.app
 let isiOSAssets = bundleUrl.indexOf('file:///') >= 0 && bundleUrl.indexOf('WeexDemo.app') > 0;
 if (isAndroidAssets) {
     nativeBase = 'file://assets/dist/';
 } else if (isiOSAssets) {
     nativeBase = bundleUrl.substring(0, bundleUrl.lastIndexOf('/') + 1);
 } else {
    let host = 'localhost:8080';
    let matches = /\/\/([^\/]+?)\//.exec(bundleUrl);
    if (matches && matches.length >= 2) {
        host = matches[1];
    }
    nativeBase = 'http://' + host + '/index.html?page=./dist/';
 }
 return nativeBase;

3浸船、樣式sass\scss

?sass妄迁,后期必不可少的利器。

?當你的weex項目不斷變大李命,一些樣式共享登淘,公共顏色,大小尺寸等的管理封字,就是你需要面對的問題黔州。

?這時候sass和scss就可以起到很大的作用耍鬓。最大優(yōu)點是,它可編程流妻,支持定義變量牲蜀,而且不像閹割后的css一樣,var()這種寫法無法在native下得到支持绅这,這時候sass的效果絕對讓你回味無窮涣达。

?使用sass也十分簡單,簡單配置下webpack证薇,sass的語法也十分容易上手度苔,只需十分鐘了解下就可以愉快的享用這塊糖了。

  • 先安裝sass依賴:
npm install node-sass;
npm install sass-loader; //依賴node-sass
  • 之后webpack.common.conf.js中配置loader浑度,如下圖寇窑,在兩個module處,增加紅框配置箩张。
  • 最后用 import 引入的sass文件進行加載甩骏,詳細可查看demo工程。
//也可以 lang="scss"
<style lang="sass">
//導(dǎo)入寫好的文件
@import "./style.scss";
</style>

五伏钠、蹲坑

?其實就是問題集錦横漏,記錄一些開發(fā)過程中遇到的問題,相信你會喜歡:

  • 1熟掂、關(guān)于vue的<scrpit>標簽內(nèi)缎浇,weex.requireModule(包括插件weex-ui)中,在全局獲取返回null的原因赴肚,是因為entry.js中的router對象,不能用import 和 export default素跺,只能用require 和 module.exports 配合。

  • 2誉券、es6一些語法問題指厌,如async和await,可以用"babel-plugin-transform-runtime"踊跟,在.babelrc中設(shè)置踩验。

{
"presets": [
"es2015",
"stage-0"
],
"plugins": [ [
"transform-runtime",
{
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": "babel-runtime"
}
]]
}
  • 3、export default 和require混合使用的時候商玫,會多一個default對象箕憾,比如this.$store.default.state這樣才對的問題。

  • 4拳昌、自定義的js文件類中袭异,不能使用全局的weex.requireModule

  • 5炬藤、使用weex-ui的tabbar結(jié)合是御铃,<list>必須有高度碴里,或者overflow屬性為scroll才能滑動,而且overflow的位置必須是不會影響其他頁面位置上真。

  • 6咬腋、全屏默認height 1334 和 width 750,但是記得減去32大概高度的statusbar睡互。

  • 7帝火、list的loadmore,必須給list設(shè)置高度樣式湃缎,才能在web中正常觸發(fā)。

  • 8蠢壹、text的</text>結(jié)束標簽換行嗓违,在debug下可能會出現(xiàn)樣式問題。

  • 9图贸、生命周期在web中與android等不同蹂季,比如activated等。

  • 10疏日、()=> {}對于this可能獲取存在的不同偿洁,盡量用function(){}。

  • 11沟优、多頁即創(chuàng)建多個類似entry.js的入口文件涕滋,在webpack下配置weex的打開生成的js文件,用于navigator跳轉(zhuǎn)挠阁,通過url傳值宾肺。

  • 12、android多頁面打開失敗

android.os.FileUriExposedException問題:

在你的Application中添加:
if (Build.VERSION.SDK_INT>=18) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();
}

ActivityNotFoundException問題:

 <activity
         android:name=".xxxxxx"
         android:label="@string/app_name"
         android:screenOrientation="portrait"
         android:theme="@style/AppTheme.NoActionBar">
     <intent-filter>
         <action android:name="com.taobao.android.intent.action.WEEX"/>

         <category android:name="android.intent.category.DEFAULT"/>
         <category android:name="com.taobao.android.intent.category.WEEX"/>
         <action android:name="android.intent.action.VIEW"/>

         <data android:scheme="http"/>
         <data android:scheme="https"/>
         <data android:scheme="file"/>
         <data android:scheme="wxpage" />
     </intent-filter>
 </activity>
  • 13侵俗、多頁面生成js時锨用,import的時候,需要指定.vue后綴的隘谣。

  • 14增拥、如果是webstorm,記得對.temp dist node_modules platforms幾個文件夾寻歧,右鍵設(shè)置excluded掌栅,避免一直indexing和硬盤資源消耗。

  • 15熄求、@viewappear="onappear" @viewdisappear ="ondisappear" 類似onPause和onResume

  • 16渣玲、ios實時看log,可以先增加

-(void)redirectConsoleLog{
#ifdef DEBUG
    NSString *documentDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    NSLog(@"documentPath : %@",documentDir);

    //重定向NSLog
    NSString* logPath = [documentDir stringByAppendingPathComponent:@"console.log"];
    freopen([logPath fileSystemRepresentation], "a+", stderr);
#endif
}
//調(diào)用
[self redirectConsoleLog];

然后在Devices下弟晚,找到對應(yīng)的模擬器號碼忘衍,在再Application下逾苫,搜索console.log,跟蹤執(zhí)行

tail -f
/Users/your name/Library/Developer/CoreSimulator/Devices/FDEACA11-D84E-4E8F-A6B8-26239559A928/data/Containers/Data/Application/9394D6CC-6B4A-4200-A13D-0CBE6F2BB67A/Documents/console.log

最后

1枚钓、文章配套铅搓,超完整 Weex 項目了解下:https://github.com/CarGuo/GSYGithubAppWeex

2、react native相關(guān)文章

從Android到React Native開發(fā)(一搀捷、入門)

從Android到React Native開發(fā)(二星掰、通信與模塊實現(xiàn))

從Android到React Native開發(fā)(三、自定義原生控件支持)

從Android到React Native開發(fā)(四嫩舟、打包流程和發(fā)布為Maven庫)

還記得我嗎
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末氢烘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子家厌,更是在濱河造成了極大的恐慌播玖,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饭于,死亡現(xiàn)場離奇詭異蜀踏,居然都是意外死亡,警方通過查閱死者的電腦和手機掰吕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門果覆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人殖熟,你說我怎么就攤上這事局待。” “怎么了菱属?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵燎猛,是天一觀的道長。 經(jīng)常有香客問我照皆,道長重绷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任膜毁,我火速辦了婚禮昭卓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瘟滨。我一直安慰自己候醒,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布杂瘸。 她就那樣靜靜地躺著倒淫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪败玉。 梳的紋絲不亂的頭發(fā)上敌土,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天镜硕,我揣著相機與錄音,去河邊找鬼返干。 笑死兴枯,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的矩欠。 我是一名探鬼主播财剖,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼癌淮!你這毒婦竟也來了躺坟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤乳蓄,失蹤者是張志新(化名)和其女友劉穎瞳氓,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體栓袖,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年店诗,在試婚紗的時候發(fā)現(xiàn)自己被綠了裹刮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡庞瘸,死狀恐怖捧弃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情擦囊,我是刑警寧澤违霞,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站瞬场,受9級特大地震影響买鸽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贯被,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一眼五、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧彤灶,春花似錦看幼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至搏熄,卻和暖如春棚唆,著一層夾襖步出監(jiān)牢的瞬間暇赤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工瑟俭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留翎卓,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓摆寄,卻偏偏與公主長得像失暴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子微饥,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容