Weex原理之帶你去蹲坑

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

兩個(gè)字,講究

***** 本文配套,超完整 Weex 項(xiàng)目推薦 : GSYGithubAppWeex *****

一、簡介

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

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

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

?作為兩個(gè)框架的深度體驗(yàn)者,個(gè)人總結(jié)出上面的對(duì)比,其中可以看出:

  • React Native更適合開發(fā)完整的App,因?yàn)樗男阅茌^好,第三方插件豐富,社群活躍并且維護(hù)較好,文檔完整等(本篇主角是Weex好吧魂淡(#?Д?))。

  • Weex更適合開發(fā)單頁面集成,這也是阿里的業(yè)務(wù)特性。
    當(dāng)然Weex也可以開發(fā)完整的多頁面App,同時(shí)我也是這么用過,不過效果對(duì)比React Native,顯然強(qiáng)差人意。

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

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

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

這就是,所謂的前言吧

二、原理

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

?Weex主要包括三大部分:JS Bridge、RenderDom,分別對(duì)應(yīng)WXBridgeManager、WXRenderManager、WXDomManager 。通過WXSDKManager統(tǒng)一管理。其中JS BridgeDom運(yùn)行在獨(dú)立的HandlerThread中,而Render運(yùn)行在UI線程。JS Bridge主要用來和 JS 端實(shí)現(xiàn)進(jìn)行雙向通信,比如把js端的dom結(jié)構(gòu)傳遞給Dom線程。Dom主要是用于負(fù)責(zé)dom的解析、映射、添加等等的操作,最后通知UI線程更新。而Render負(fù)責(zé)在UI線程中對(duì)dom實(shí)現(xiàn)渲染。

?如下圖,是生成dom,dom的解析,映射,添加,渲染的流程。

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

?如上可知,因?yàn)镴S端運(yùn)行于獨(dú)立的單線程中,所以為了保證運(yùn)行的流暢性,一般需要避免在JS端執(zhí)行耗時(shí)操作,比如:網(wǎng)絡(luò)請(qǐng)求,圖片加載等,其實(shí)都是在原生端完成,js端執(zhí)行的是發(fā)起一個(gè)請(qǐng)求和響應(yīng)一個(gè)結(jié)果。同時(shí)因?yàn)樵伺cJS端是通過JS Bridge通訊,所以也需要盡量避免大數(shù)據(jù)和頻繁的通訊,導(dǎo)致響應(yīng)的延遲。

?原生端的dom的加載解析映射,也是性能的一大瓶頸。一般而言,Weex在Web端生成的,是通過webpack的webConfig打包成單頁面的index.web.js文件;而在原生端,一般會(huì)通過webpack的weexEntry配置成多頁面形式:即每一個(gè)需要獨(dú)立的.vue的頁面,最終會(huì)被打包成一個(gè).js文件。所以打開每個(gè)頁面時(shí)加載對(duì)應(yīng)的js文件,這很好的減小了需要加載的文件大小,提高了dom的解析效率。最后,Weex默認(rèn)打的js只包含業(yè)務(wù)js代碼,基礎(chǔ)js庫已經(jīng)被包含在weex sdk中,也使得體積會(huì)小很多。

三、入門

1、配置環(huán)境

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

2、快速入門

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

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

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

請(qǐng)忽略那個(gè)this,真的( ̄. ̄)

?如上圖(請(qǐng)忽略那個(gè)this( ̄. ̄)),這就是一個(gè)極度簡化的,用Vue寫的Weex頁面。效果是從顯示Hello World ,一秒變I’m CarGuo,就是這么自信。

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

?因?yàn)樾枰С秩?,Weex在Vue的基礎(chǔ)上閹割了一些標(biāo)簽、css樣式和事件,具體可見與 Web 平臺(tái)的差異

?其中,在Android和IOS上,<text> <image>等標(biāo)簽,其實(shí)是被編譯為原生控件,這就是上面所說的dom解析,同時(shí)你也可以在原生端,自定義控件或者功能模塊,然后注冊(cè)到weex中使用,實(shí)際上weex提供的基礎(chǔ)控件和功能模塊并不多,但卻很容易拓展,具體可見 拓展原生端功能

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

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

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

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

目瞪狗帶

? 題外話 :說到跨平臺(tái)開發(fā),也許你聽說過cordova這位老大哥,它曾是早期的跨平臺(tái)開發(fā)潮流,cordova提供豐富的原生插件和打包功能:通過webview把前端頁面打包成一個(gè)App,通過插件提供前端需要的原生接口,交互通過webview的js接口支持。為什么說起它呢,是因?yàn)閃eex中,你可以看到很多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綁定到界面。它的用處在于可以在多個(gè)vue組件間,方便的同步數(shù)據(jù),更新界面。

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

? iconfont :矢量圖標(biāo),少不了iconfont,通過字庫生成圖標(biāo),資源豐富,絕對(duì)值得推薦。
? weex-ui: weex中難得的良心官方封裝庫。
? eros :eros 不是框架,是基于 weex 封裝、面向前端的 vue 寫法的一整套 APP 開源解決方案,是由本木醫(yī)療大前端團(tuán)隊(duì)經(jīng)過大量實(shí)踐沉淀而出。。

四、深入填坑

1、ES6、ES7

? 說到 Javascript ,ES6、ES7必須了解下。Weex中默認(rèn)就有對(duì)其支持,但是對(duì)于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默認(rèn)是單頁面效果,也就是Android中一個(gè)Activity的概念,而單頁面效果在原生上,跳轉(zhuǎn)一多效果就會(huì)web了。既然叫native,怎么可能如此too young,所以這個(gè)時(shí)候,就需要修改默認(rèn)的webpack,讓其支持naive多頁面了?╮(╯▽╰)╭。

?首先,要知道Weex真正運(yùn)行的是,通過entry.js作為入口文件文件,通過webpack,將.vue文件打包成index.js進(jìn)行使用。Look,多頁面的重點(diǎn),就是將獨(dú)立頁面的.vue文件,生成多個(gè)js文件。

入口js

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

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

webpack.common.conf.js

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

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

 //獲取當(dāng)前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,后期必不可少的利器。

?當(dāng)你的weex項(xiàng)目不斷變大,一些樣式共享,公共顏色,大小尺寸等的管理,就是你需要面對(duì)的問題。

?這時(shí)候sass和scss就可以起到很大的作用。最大優(yōu)點(diǎn)是,它可編程,支持定義變量,而且不像閹割后的css一樣,var()這種寫法無法在native下得到支持,這時(shí)候sass的效果絕對(duì)讓你回味無窮。

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

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

五、蹲坑

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

  • 1、關(guān)于vue的<scrpit>標(biāo)簽內(nèi),weex.requireModule(包括插件weex-ui)中,在全局獲取返回null的原因,是因?yàn)閑ntry.js中的router對(duì)象,不能用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混合使用的時(shí)候,會(huì)多一個(gè)default對(duì)象,比如this.$store.default.state這樣才對(duì)的問題。

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

  • 5、使用weex-ui的tabbar結(jié)合是,<list>必須有高度,或者overflow屬性為scroll才能滑動(dòng),而且overflow的位置必須是不會(huì)影響其他頁面位置。

  • 6、全屏默認(rèn)height 1334 和 width 750,但是記得減去32大概高度的statusbar。

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

  • 8、text的</text>結(jié)束標(biāo)簽換行,在debug下可能會(huì)出現(xiàn)樣式問題。

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

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

  • 11、多頁即創(chuàng)建多個(gè)類似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時(shí),import的時(shí)候,需要指定.vue后綴的。

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

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

  • 16、ios實(shí)時(shí)看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下,找到對(duì)應(yīng)的模擬器號(hào)碼,在再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 項(xiàng)目了解下:https://github.com/CarGuo/GSYGithubAppWeex

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

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

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

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

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

還記得我嗎
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容