您好,登錄后才能下訂單哦!
這篇文章主要介紹了Vue中Weex怎么用,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
一、開發環境
在這個 Weex app 開發中,我的開發環境相關配置如下:
工具名稱 | 版本號 |
---|---|
Node.js | 8.2.1 |
Npm | 5.3.0 |
Android Studio | 3.2 |
Weex | 2.0.0-beta.17 |
JDK | 1.8 |
Weex-ui | 0.6.14 |
2.1、Weex 理念二、Weex 介紹
“Write once, run everywhere”, Weex 的定義就像是:寫個 vue 前端,順便幫你編譯成性能還不錯的 apk 和 ipa(當然,現實有時很骨感)。基于 Vue 設計模式,支持 web、android、ios 三端,原生端同樣通過中間層轉化,將控件和操作轉化為原生邏輯來提高用戶體驗。 在 weex 中,主要包括三大部分:JS Bridge、Render、Dom,分別對應WXBridgeManager、WXRenderManager、WXDomManager,三部分通過 WXSDKManager 統一管理。其中 JS Bridge 和 Dom 都運行在獨立的 HandlerThread 中,而 Render 運行在 UI 線程。 JS Bridge 主要用來和 JS 端實現進行雙向通信,比如把 JS 端的 dom 結構傳遞給 Dom 線程。Dom 主要是用于負責 dom 的解析、映射、添加等等的操作,最后通知 UI 線程更新,而 Render 負責在 UI 線程中對 dom 實現渲染。
Weex 所有的標簽也不是真實控件,JS 代碼中所生成存的 dom,最后都是由 Native 端解析,再得到對應的 Native控件渲染,如 Android 中標簽對應 WXTextView 控件。 Weex 中文件默認為 .vue ,而 vue 文件是被無法直接運行的,所以 vue 會被編譯成 .js 格式的文件,Weex SDK會負責加載渲染這個 js 文件。Weex 可以做到跨三端的原理在于:在開發過程中,代碼模式、編譯過程、模板組件、數據綁定、生命周期等上層語法是一致的。不同的是在 JS Framework 層的最后,web 平臺和 Native 平臺,對 Virtual DOM 執行的解析方法是有區別的。
2.2 創建 Weex 項目
Weex 提供了一個命令行工具 weex-toolkit 來幫助開發者使用 Weex,它可以用來快速創建一個空項目、初始化 iOS 和 Android 開發環境、調試、安裝插件等操作。
我們可以通過以下步驟創建一個基礎的 Weex 項目:
(1)安裝 weex-toolkit 工具
npm install weex-toolkit -g
(2)創建新項目
weex create weex_project
(3)安裝項目依賴
cd weex_project npm install
(4)啟動項目
npm start
項目啟動完畢,瀏覽器窗口會自動打開項目首頁,如下圖所示:
(5)添加 原生Android 平臺
weex platform add android
(6)運行下面的命令,可以在模擬器或真實設備上啟動 Android 應用:
weex run android
2.3、運行Weex項目
2.3.1、啟動服務端應用
(1)進入目錄 weex_project/backend/,安裝服務端應用所需要的插件包:
$ npm install
(2)啟動服務端應用
$ npm run start
2.3.2、啟動 Weex 應用
(1)如果你還沒安裝 weex 工具,可以運行以下命令進行安裝:
$ npm install -g weex-toolkit
(2)安裝項目需要的插件包:
$ npm install
(3)啟動項目:
$ npm run start
三、Weex 常用的 VSCode 插件
Weex為VSCode提供了一些常用的插件,可以提高開發效率:
weex-new-project - 用于在 VSCode 中創建Weex項目;
weex-lang - 用于在 VSCode 中對最新的 Weex 語法進行支持;
weex-doctor - 用于檢查 iOS 和 Android 本地開發環境;
weex-debugger - 用于在 VSCode 中啟動Weex調試工具;
weex-run - 用于在熱更新模式下啟動 Android 及 iOS 工程;
3.1、weex-run
可以使用截圖的步驟來安裝 weex-run插件,可以自行搜索如何安裝VSCode插件。
(2)啟動 Android 項目
啟動成功控制臺會輸出一堆日志,如下圖。
Weex自帶熱更新功能,接下來,我們查看 Android 項目的熱更新。
3.2、weex-debugger
(1)安裝 weex-debugger 插件,安裝過程和安裝weex-run插件類似。
(2)ctrl + shift + p 彈出命令輸入框,如下圖所示輸入:weex debug,然后網頁會出現第 2 張截圖的二維碼:
(3)用手機的 Weex Playground App 的二維碼進行掃描,出現以下調試頁面(一定一定要注意,手機連的 WiFi 和 你開發本地網絡在同一局域網)。
(4)再用手機的 Weex Playground App 的二維碼掃描 Weex 應用的二維碼,調試頁面就會變成對應的 Weex 應用的調試頁面,如下圖所示。
四、Weex 項目實戰
4.1、項目目錄路徑
下面通過一個Weex 項目來說明Weex的一些基礎,項目目錄結構如下:
4.2、功能模塊設計
考慮到更好的體驗 Weex 和 H5 在開發效率、功能性能、用戶體驗等方面的差異性,我們對功能模塊進行精心設計,主要基于我們現有的實際項目的業務進行開發,并結合移動端特有的特性。
相關的模塊功能設計如下圖所示,其中紅色標注部分表示,受限于開發資源、Weex 生態方面原因,我們暫時還沒完成全部功能的開發。
4.3、功能界面展示
下面是Weex示例項目截取一些功能界面展示,如下圖:
4.4、重要功能介紹
除了一些常規的功能開發外,以下介紹的幾個功能在 Weex 官網中并沒有詳細介紹或者根本沒有介紹,我們在開發過程中踩了不少坑,因此將踩坑經驗進行匯總,幫助大家避免踩坑:
(1)登錄 token 認證
(2)圖片選擇/上傳功能
(3)websocket 功能實現
(4)手機物理鍵返回上一級功能
(5)Android 如何顯示本地圖片
4.4.1、token 認證功能
(1)token 認證介紹
在 Web 領域基于 token 的身份驗證隨處可見。在大多數使用 Web API 的互聯網公司中,tokens 是多用戶下處理認證的最佳方式。token 具有以下特性:
無狀態、可擴展
支持移動設備
跨程序調用
安全
基于 token 的身份驗證的過程如下:
用戶通過用戶名和密碼發送請求。
服務端程序驗證。
程序返回一個簽名的 token 給客戶端。
客戶端儲存 token,并且每次用于每次發送請求。
服務端驗證 token 并返回數據。
(2)weex 和 express 之間實現 token 認證
express 服務端主要使用 express-jwt 插件,express-jwt 是 nodejs 的一個中間件,內部對 jsonwebtoken 進行封裝使用。express-jwt 會驗證指定 http 請求的 jsonwebtoken 的有效性,如果有效就將 jsonwebtoken 的值設置到 req.user 里面,然后跳轉到相應的 router。
以下是服務端 express 的代碼邏輯,代碼如下:
var expressJWT = require('express-jwt'); // token 設置 app.use(expressJWT({ secret: CONSTANT.SECRET_KEY }).unless({ // 除了以下配置的地址,其他的URL都需要驗證 path: ['/getToken', /^\/public\/.*/, /^\/user_disk\/.*/] })); // 登錄時,需要進行用戶密碼認證,相應路由跳轉到下面一步 app.use('/getToken', tokenRouter); // 當用戶密碼正確時,我們進行 token 設置 data: { token: jsonWebToken.sign({ uid: obj.uid }, CONSTANT.SECRET_KEY, { expiresIn: 60 * 60 * 1 }), }
對應的Weex的代碼如下:
// Weex 登錄邏輯 login () { let param = { uid: this.uid, password: this.password }; let options = { url: '/getToken', method: 'POST', body: JSON.stringify(param) }; let vm = this; api.fetch(options, function (ret) { if (ret.ok && ret.data.code === 0) { // 前端可以獲取到服務端返回的 token ,并將其作為全局變量 global.token = 'Bearer ' + ret.data.data.token; vm.$router.push('/tabIndex'); } else { modal.toast({ message: '用戶認證失敗!', duration: 1 }); } }); } // Weex 的每次請求,頭部都帶上 token initOptions.headers['Authorization'] = global.token;
經過以上代碼邏輯處理后,我們查看 Weex 向服務端發送的請求頭部,都攜帶了 token,如下圖所示。這樣服務端 express 處理這個請求時,就可以通過解析 token 獲取到對應的用戶 id ,從而允許其對服務端的數據訪問。
4.4.2、圖片選擇/上傳功能
(1)存在問題
很遺憾,Weex 竟然沒有提供文件選擇/上傳的模塊,對于前端開發者來說無疑晴天霹靂,那我不是要手動去寫 Android 的 java 代碼,經過反復查找,真的沒有文件選擇/上傳模塊,于是我們只能自己去寫 Java 代碼去實現 Android 端圖片選擇以及上傳功能。當然,也可以使用一些第三方的插件。
(2)實現 Android 原生的圖片選擇/上傳功能
在 weex_projectplatformsandroidappsrcmainjavacomweexappextend 目錄下新建 圖片上傳 模塊的類 WXAlbumModule ,其繼承 WXModule ,其主要兩個方法為 choosePhoto 和 onActivityResult ,其中 choosePhoto 用于給 Weex 前端來調用,當 Weex 前端需要選擇相冊中的圖片時,Weex 前端就調用 choosePhoto 方法;onActivityResult 是用戶選擇好相冊中的圖片后,會相應觸發該事件,并將用戶選擇的相片以參數形式傳入 onActivityResult ,從而我們可以在 onActivityResult 中進行圖片的上傳邏輯,圖片上傳完成后,Android 端會在回調事件中通知前端,圖片放置在服務端的目錄路徑,前端可以對應進行圖片顯示等操作。關鍵代碼邏輯如下,如果如果對 Java 完全一無所知的同學可以先不看,懂 java 代碼的建議結合項目代碼來看,會更清晰。
例如,下面是Android端封裝的
@JSMethod(uiThread = true) // 給 Weex 前端調用,當用戶點擊時,調用該函數 public void choosePhoto(String param, JSCallback callback) { if (ContextCompat.checkSelfPermission(mWXSDKInstance.getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions((WXPageActivity) mWXSDKInstance.getContext(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_REQUEST_CODE); } else { choosePhoto(); } try{ JSONObject jsonObject = new JSONObject(param); this.type = (String)jsonObject.get("type"); this.path = (String)jsonObject.get("path"); this.url = (String)jsonObject.get("url"); this.token = (String)jsonObject.get("token"); }catch (JSONException e){ e.printStackTrace(); } this.callback = callback; }
選擇完成后,系統會返回圖片的信息,此時就可以進行上傳操作,如下所示:
@Override // 用戶選擇好相冊中的圖片后,會相應觸發該事件,并將用戶選擇的相片以參數形式傳入 public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == WXPageActivity.RESULT_OK) { switch (requestCode) { case CAMERA_REQUEST_CODE: { try { Uri selectedImage = data.getData(); String[] filePathColumns = {MediaStore.Images.Media.DATA}; Cursor c = mWXSDKInstance.getContext().getContentResolver().query(selectedImage, filePathColumns, null, null, null); c.moveToFirst(); int columnIndex = c.getColumnIndex(filePathColumns[0]); String picturePath = c.getString(columnIndex); c.close(); //上傳的文件 File file = new File(picturePath); // 普通參數 HashMap<String , String> params = new HashMap<>(); params.put("path", this.path); uploadForm(params, "file", file, "", this.url); } catch (Exception e) { e.printStackTrace(); } break; } } } super.onActivityResult(requestCode, resultCode, data); }
實現好以上選擇圖片和上傳圖片的代碼邏輯后,我們需要在 weex_projectplatformsandroidappsrcmainjavaWXApplication.java 中進行模塊的注冊,代碼邏輯如下:
WXSDKEngine.registerModule("wxalbum", WXAlbumModule.class);
然后,Weex 前端調用注冊的原生模塊即可,如下所示:
const WXAlbum = weex.requireModule('wxalbum'); upload () { let path = 'public/upload/'; let vm = this; storage.getItem('token', event => { let param = { type: 'image/jpeg', // 選擇的數據類型 path: path, url: CONSTANT.SERVER_URL + '/users/upload', token: event.data }; WXAlbum.choosePhoto(JSON.stringify(param), ret => { let obj = JSON.parse(ret); vm.imgPath = '/' + path + obj.file[0].originalFilename; modal.alert({ message: vm.imgPath, okTitle: '確認' }, function () { console.log('alert callback') }) }); }) },
4.4.3、WebSocket 功能實現
(1)存在問題
Weex 官網的 webSocket 章節特意標注以下警告字眼:
h6 提供 WebSockets 的 protocol 默認實現,iOS 和 Android 需要自定義實現,Android 可參考:
DefaultWebSocketAdapter.java
DefaultWebSocketAdapterFactory.java
好吧,根本沒有封裝 WebSocket 功能,那我就按官網給的參考來實現吧,于是,我點擊前面兩個參考鏈接,鏈接打開的頁面根本不存在,報 404(官網出現這種問題,實在不應該啊)。網上谷歌搜索一圈,沒有發現類似的問題,還是主要查看了這個給的 url 以及結合阿里將 weex 貢獻給 Apache 維護這個事情,猜測是不是 Weex 捐給 Apache 維護,github 的庫目錄更改,但是官網對應的 url 地址沒有做修改。經過查找,確實是這個問題,在舊庫中以下目錄找到官網提的:DefaultWebSocketAdapter.java 和 DefaultWebSocketAdapterFactor.java :
https://github.com/alibaba/weex/tree/master/android/commons/src/main/java/com/alibaba/weex/commons/adapter
(2)手動實現 WebSocket 功能
我們 在 weex_projectplatformsandroidappsrcmainjavacomweexappadapter 目錄底下創建 Websocket 的實現類 DefaultWebSocketAdapter.java 和工廠創建類 DefaultWebSocketAdapterFactory.java ,關鍵邏輯代碼如下:
// 該類主要實現 Websocket 的連接、發送消息、接收消息、關閉等函數或事件 public class DefaultWebSocketAdapter implements IWebSocketAdapter { @Override public void connect(){...} @Override public void send(String data) {...} @Override public void close(int code, String reason) {...} @Override public void destroy() {...} ... }
然后,為該類主要為創建 Websocket 對象的工廠類:
// 該類主要為創建 Websocket 對象的工廠類 public class DefaultWebSocketAdapterFactory implements IWebSocketAdapterFactory { @Override public IWebSocketAdapter createWebSocketAdapter() { return new DefaultWebSocketAdapter(); } }
接下來,在 weex_projectplatformsandroidappsrcmainjavacomweexappWXApplication.java 中初始化 Websocket ,如下所示:
WXSDKEngine.initialize(this, new InitConfig.Builder().setImgAdapter(new ImageAdapter()). setWebSocketAdapterFactory(new DefaultWebSocketAdapterFactory()).build() );
然后,在 Weex 的前端中導入Websocket模塊,就可以使用 Websocket,相關代碼如下:
const ws = weex.requireModule('webSocket'); ws.WebSocket(CONSTANT.SOCKET_WS, ''); // 需要注意 web 端的寫法和 android 端的寫法不一樣 // android 的 onxx 事件是一個方法,需要傳入一個JSCallback的值, if (weex.config.env.platform === 'Web') { ws.onmessage = this.socketMessage; } else { ws.onmessage(this.socketMessage); }
4.4.4、點擊手機物理鍵返回上一級功能
(1)存在問題
我們開發的 Weex app,如果在 app 的哪個界面,點擊手機的返回上一級物理鍵,都會導致 app 退出,好吧,Weex 也沒有提供對應的事件處理,我們不得不自己再去寫安卓的 java 代碼去向 Weex 的 Web 端拋出這個事件。
(2)重寫手機物理鍵返回上一級的處理邏輯
正常交互邏輯:當處于主界面時,返回上一級物理鍵會進行提示“再點擊一次退出”,如果不是處于主界面時,會返回上一級頁面。
首先,我們在 weex_projectplatformsandroidappsrcmainjavacomweexappWXPageActivity.java 中添加監聽點擊手機物理鍵的事件,如下所示:
public void onBackPressed(){ Map<String,Object> params=new HashMap<>(); params.put("name","msg"); mInstance.fireGlobalEventCallback("androidback",params); }
在 Weex 的 vue 入口文件中,監聽 androidback 事件,當接收到該事件時,進行相應的邏輯處理,代碼如下所示:
listenAndroidBack () { let vm = this; globalEvent.addEventListener('androidback', function (e) { if (vm.$route.name === 'tabIndex' || vm.$route.name === 'loginPage') { if (vm.exitFlag) { weex.requireModule('wxclose').closeApp(); } else { modal.toast({ message: '再點一次退出', duration: 1 }); vm.exitFlag = true; vm.clearExitFlag(); } } else { vm.$router.go(-1); } }); },
4.4.5、Android 顯示本地圖片
(1)存在問題
Weex 官網中 image 圖片組件顯示項目目錄下圖片,src 地址直接寫成相對路徑,如下所示;但是這種寫法存在問題,它只支持 web 端的顯示,在 Android 端是無法顯示的,找不到對應圖片。
<image ref="poster" src="path/to/image.png"></image>
(2)Android/IOS 端顯示本地圖片
Weex 沒有在將 vue 編譯成 Android 組件時,對應將圖片放置到 Android 對應的目錄下,所以我們只好自己將圖片手動再放置一份,其中 Android 端需要額外將圖片放在 /platforms/android/app/src/main/res/drawable-xxhdpi ,IOS 放入xcode 底下的 /Source/images/下 ,然后我們在代碼邏輯中,根據環境判斷現在是 Web 環境、Android 環境或者 IOS 環境,再對應的獲取對應目錄下的圖片(暫時只能做到這種程度了...),如下代碼所示:
const ICON_URL = { Web: `${WEB_IMAGE_URL}`, android: `local:///${pureName}`, iOS: `local:///filePng/${pureName}${suffixName}` } return ICON_URL[CUR_RUN_PLATFORM];
五、編譯 Android apk
Android apk 打包分 debug 版和 release 版,通常所說的打包指生成 release 版的 apk,release 版的 apk 會比debug 版的小,release 版的還會進行混淆和用自己的 keystore 簽名,以防止別人反編譯后重新打包替換你的應用。 下面我們主要介紹如何在 Android Studio 中對 weex 項目進行打包。
5.1、Android 平臺目錄
Android Studio 打開 Android 工程,目錄為:weex 項目 /platforms/android 。
5.2、常規的 AS 打包分為兩種
一種是沒有 “.jks” 文件的打包
一種是有 “.jks” 文件的打包
注:.jks” 文件 類似 apk 身份證;
5.3、沒有 “ .jks ” 文件的打包
(1)打包步驟如下截圖:
(2)我們點擊選擇 【Create new】創建jks
(3)填寫 key 的相關信息
(4)點擊 OK 之后,可以看到如下信息已被自動填充,并點擊打包即可。
(5)等待打包完成后,就可以查看打包好的 apk 文件
六、Weex 開發總結
6.1、官網經常無法訪問
Weex 官網經常出現無法訪問的情況,頻率大概一周至少一次;這就很影響開發效率了,因為在開發過程中需要經常查看官網的寫法、說明等,如果訪問不了,則會造成一定程度的開發 block。
6.2、官網文檔粗糙
Weex 官網的文檔比較粗糙,如果沒有比較好的前端和移動端原生開發知識儲備的話,看官網的文檔就很吃力了,官網很多講解寫的非常簡單,都默認你同時熟練前端和移動端原生開發,而且同時有較好前端和移動端原生開發人員應該在業界還比較少吧。
6.3、生態貧瘠
Weex 生態是真的貧瘠,除了阿里自己出產的組件庫 weex-ui 外,其它的相關插件幾乎找不到,有也是少于100個 star 的,例如我在項目開始前設計的一些功能:拍照、圖片選擇上傳、語音錄入、通訊、定位、文件預覽等等移動端的特有功能,都沒有插件,都需要自己去寫 Android 的原生代碼,那這時就失去了利用框架提高開發效率的意義;生態跟 react-native 差的真不是一丁半點,而是根本不是一個量級。
6.4、是否兩個 Weex 版本
結合上一點,坊間傳聞:Weex 存在兩個版本,一個版本是阿里內部使用的,一個是非阿里內部使用;這個傳言無從驗證,但是結合第2點說的 Weex 生態貧瘠,我卻無意在瀏覽器搜索中,發現了一系列常見功能的插件封裝:weex.apache.org/zh/biz-comp… ,截圖如下,但是這些插件并沒有提供出來使用,存在 Weex 官網中,但是卻沒有訪問入口。如果這些插件功能能提供使用,無疑將很大程度豐富 Weex 的生態。
6.5、三端兼容性不好
Weex 號稱 “一次撰寫,多端運行”,但是存在很多兼容性問題,比如我們在 Web 端調試開完后一個功能模塊,但是在 Android 端一運行,就各種跑不通,各種兼容性問題;這種問題導致,我們后期根本不敢在 Web 環境開發,例如:我們這個項目是想開發個 Android 的 app,我們最終都直接在 Android 環境下開發,這種效率肯定就沒有在 Web 環境開發效率高。
6.6、Vue 支持度不夠
Weex 默認集成 Vue 框架,而且主打 Vue 受眾,但是 Weex 對 Vue 的支持度還不夠,除了官網上提到的那些 vue 特性不支持外,還有很多特性沒有被列出,例如:vuex 等。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Vue中Weex怎么用”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。