Weex 是阿里於 2016 年開源的一款開發框架,它的介紹是:javascript
Weex 是一個使用 Web 開發體驗來開發高性能原生應用的框架。css
它使用了 Web 技術來開發 Android、IOS 應用,從而達到更快的迭代速度,同時下降了開發原生應用的門檻,
達到生產力和性能共存。html
Weex 設計之初是爲了和原有應用進行兼容開發,和 NativeScript 不一樣,它只須要在項目中添加 Weex 的 SDK 便可使用。
它的定位不是所有應用,目標是針對部分變更頻繁的應用。它是一種解耦的應用,每一個頁面相對獨立,經過路由的方式對調用各頁面,
經過 API 的方式與設備進行交互。因此能夠看到官網上 Weex 的結構圖:前端
Weex 作一個簡單一些的例子仍是比較合適的。本文以仿開眼部分功能爲例作一小應用。先看下效果圖:vue
首先須要準備好 npm 環境、Android 環境,IOS 環境,因爲在 mac 下直接安裝 xcode 就具有 IOS 環境了,且 npm 是前端必備開發環境的,就無需再安裝了。Android 環境的安裝能夠直接安裝 Android Studio,一鍵配置好環境。java
打開控制檯,全局安裝 weexreact
npm i -g weex-toolkit weex weex-debugger
建立項目:android
weex create weex-kaiyan cd weex-kaiyan weex platform add android weex platform add ios
按照提示操做便可。安裝速度都不是很快,須要耐心等候。爲了方便開發,咱們採用 airbnb 的代碼規範,先在 devDependencies 安裝相關依賴(或者全局安裝eslint,用 eslint 的init 功能也能夠):webpack
"eslint": "^4.13.1", "eslint-config-airbnb-base": "^12.1.0", "eslint-friendly-formatter": "^3.0.0", "eslint-import-resolver-webpack": "^0.8.3", "eslint-loader": "^1.7.1", "eslint-plugin-import": "^2.8.0", "eslint-plugin-vue": "^4.0.0",
在 .eslintrc.js 中添加ios
extends: ['plugin:vue/recommended', 'airbnb-base'],
在 vscode 中啓用 lint 功能:
"eslint.validate": [ "javascript", "javascriptreact", "html", "vue" ], "eslint.options": { "plugins": ["html"] },
而後準備好要訪問的 api (https://github.com/kaikaixue/Eyepetizer/blob/master/app/src/main/java/com/xk/eyepetizer/api),這樣作完了準備工做,能夠開始開發了。
目錄結構大概是這樣子:
├── README.md ├── android.config.json ├── configs │ ├── config.js │ ├── helper.js │ ├── logo.png │ ├── plugin.js │ ├── utils.js │ ├── vue-loader.conf.js │ ├── webpack.common.conf.js │ ├── webpack.dev.conf.js │ ├── webpack.prod.conf.js │ └── webpack.test.conf.js ├── ios.config.json ├── npm-shrinkwrap.json ├── package.json ├── platforms │ ├── android │ ├── ios │ └── platforms.json ├── plugins │ └── plugins.json ├── src │ ├── api │ │ └── index.js │ ├── components │ │ ├── card-list-scroller.vue │ │ ├── card-video-no-author.vue │ │ ├── card-video.vue │ │ └── tab.vue │ ├── entry.js │ ├── index.vue │ ├── mixin-common.js │ ├── mixin-preload.js │ ├── mixin-router.js │ ├── router.js │ └── views │ ├── categories.vue │ ├── categoryHome.vue │ ├── home.vue │ ├── rank.vue │ └── videoDetail.vue ├── web │ ├── assets │ │ ├── preview.css │ │ └── qrcode.js │ ├── index.html │ └── preview.html └── webpack.config.js
其中 config 文件下是用於放 webpack 打包的配置, src 就是咱們的代碼目錄,platform 裏面放 native 代碼,
web 文件夾是咱們的 web 的 html 模板。
要實現三端開發,默認的 weex 項目模板是不行的,它的設計是爲 Native 準備的,不考慮單頁應用的方式。
雖然不推薦三端同時開發(兼容三端效率會比較低),但爲研究怎麼實現咱們仍是作一下。先安裝單頁應用必備 vue-router
而後修改 src/entry.js ,添加手動掛載 vue 的代碼,假定咱們 src 目錄下有個 router.js,
還有一個全部文件用的mixin,修改完成後的代碼以下:
import Vue from 'vue'; import weex from 'weex-vue-render'; import App from './index.vue'; import router from './router'; import mixin from './mixin-router'; weex.init(Vue); Vue.mixin(mixin); App.el = '#root'; App.router = router; const app = new Vue(App); export default app;
在 native 端這個 entry.js 是沒用的,native 端是直接使用由 weex 打包生成的 js 文件,
包括掛載都是框架作的,咱們不須要處理,因此它只是給 web 使用的。
而後設置主入口:build/webpack.common.conf.js中webEntry爲固定值:
const webEntry = { 'index': helper.rootNode(config.entryFilePath) };
同時註釋掉讀取文件內容並注入entry中
// if (extname === '.vue') { // const entryFile = path.join(vueWebTemp, dir, path.basename(file, extname) + '.js'); // fs.outputFileSync(path.join(entryFile), getEntryFileContent(entryFile, fullpath)); // webEntry[name] = path.join(entryFile) + '?entry=true'; // }
在 webpack 中添加代理,因爲 web 端有跨域問題,咱們在 configs/config.js 中添加
proxyTable: { '/api': { target: 'https://baobab.kaiyanapp.com/', changeOrigin: true, } },
如今開始像正常寫 vue 同樣開始碼代碼吧。要先注意的一點是 native 端不支持 vue-router 的特性,
須要使用 navigator 模塊進行 push 操做,因此咱們須要單獨寫個模塊,經過 mixin 方式進行兼容 頁面跳轉,
參考 https://www.jianshu.com/p/497f1a9ff33f:
const isWeex = weex.config.env.platform.toLowerCase() !== 'web'; const nav = weex.requireModule('navigator'); export default { methods: { push(path, option = {}) { if (isWeex) { const toUrl = weex.config.bundleUrl.split('/').slice(0, -1).join('/') + '/' + path.replace(/^\//, '') + '.js';// 將a.js的絕對地址轉爲b.js的絕對地址 nav.push({ url: toUrl, animated: option.animated || 'true', }); } else { this.$router.push(path);// 使用vue-router } }, pop(option = {}) { if (isWeex) { nav.pop({ animated: option.animated || 'true', }); } else { window.history.back(); } }, }, };
這樣咱們在寫跳轉時候就能夠寫成:
this.push('/videoDetail')
同時準備好你須要的 api 庫模塊(我用的 axios),以及其餘公衆模塊,好比說 storage 。Weex 中的 Storage 模塊是爲了兼容 web 版本,接口和 web 版本的 LocalStorage 比較相似,只是異步形式。爲方便,咱們能夠將回調式轉爲 Promise 式:
function callStorage(type) { return function callMethod(...args) { const storage = this.$storage; return new Promise((resolve, reject) => { const callback = (e) => { if (e && e.result === 'success') { resolve(e.data); } else { reject(e); } }; storage[type].call(storage, ...args, callback); }); }; } class Storage { constructor() { this.$storage = weex.requireModule('storage'); } setItem = callStorage('setItem') getItem = callStorage('getItem') removeItem = callStorage('removeItem') }
而後在 Mixin 中使用它便可。若是你有精力的話,能夠設計一個基於 storage 的數據傳遞模塊。
開發頁面就和寫 vue 同樣啦,只是要注意一些點:
包括在開發階段,咱們也是須要對 native 端進行效果驗證的。Weex 提供了一個簡單的命令:
weex run android weex run ios npm run dev
若是已經配置了 IOS 環境,直接運行命令就能夠了。不過默認的主頁是 index.js,
能夠在 android.config.json 和 ios.config.json 中分別配置 WeexBundle 選項便可。
須要注意的是,運行狀態下默認是打開本地文件的,而運行命令是不會放 views 文件夾目錄過去,
須要手動拷貝一下。安卓下面因爲訪問本地文件的接口在 7.0 下有問題,
建議在 app_config.xml 中修改 launch_locally 爲 false, 並指定好遠程地址。
調試沒問題後,咱們按照 Android 和 IOS 各自的方案進行打包便可.
因爲本身對 Native 開發瞭解得很少,因此好多東西只知其一;不知其二,並且 Weex 的包總能發現各類小問題, 須要強大的耐心去解決或者規避這些問題,只能祝使用的人好運吧。新出的 weex-ui 雖然已經開源很久了, 有時間能夠嘗試下,不過因爲核心模塊沒有開源,好多組件不能使用,先觀望一段時間,等有好的點子再試試。