?本篇將節(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 Bridge、Render睡汹、Dom肴甸,分別對應(yīng)WXBridgeManager
、WXRenderManager
囚巴、WXDomManager
原在。通過WXSDKManager
統(tǒng)一管理。其中JS Bridge和Dom運行在獨立的HandlerThread中彤叉,而Render運行在UI線程庶柿。JS Bridge主要用來和 JS 端實現(xiàn)進行雙向通信,比如把js端的dom結(jié)構(gòu)傳遞給Dom線程秽浇。Dom主要是用于負責dom的解析浮庐、映射、添加等等的操作柬焕,最后通知UI線程更新审残。而Render負責在UI線程中對dom實現(xiàn)渲染。
?如下圖斑举,是生成dom搅轿,dom的解析,映射富玷,添加璧坟,渲染的流程。
?如上可知赎懦,因為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( ̄. ̄))譬巫,這就是一個極度簡化的宙橱,用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
的存在感。
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文件因块。
?如上圖,參考entry.js
文件籍铁,創(chuàng)建一個SecondPageEntry.js涡上,作為SecondPage.vue的入口,用于webpack生成SecondPage.js頁面拒名。
?什么吩愧?webpack沒聽說過怎么辦,No problem增显,你只需簡單的修改雁佳,一知半解完全可以勝任。如下圖同云,我們主要需要修改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庫)