系列文章的目錄在 ? 這裏html
除了 Vue 框架提供的功能覺得,Weex 平臺自己也提供了不少功能,這些功能比前端框架更底層一些,並且是跨框架通用的,在 Vue 和 Rax 裏均可以用。本文的幾個例子愈來愈偏底層,最後一個例子還須要寫 java 代碼。前端
Weex 模塊的文檔vue
經過 weex.requireModule
便可引入 weex 的模塊。java
const modal = weex.requireModule('modal') modal.toast({ message: 'native toast' })
模塊的用法很簡單,像普通 js 模塊同樣調接口就好了,看起來挺像一個 npm 模塊的,可是在 Weex 模塊內部會調用原生接口,最終調用的都是原平生臺提供的功能。Weex 的模塊提供了使用原生功能的能力。android
例如 modal
模塊能夠彈出 toast
、alert
、confirm
、prompt
等各類彈窗,這些彈窗都是原生彈窗,在 Android 和 iOS 下的風格和行爲是由各自的系統決定的。Weex 的模塊在 js 這一層只負責向原生環境裏傳遞數據,通知 native 去執行某些操做。ios
像 storage
、navigator
、clipboard
這種依賴平臺特性的功能,須要調用平臺原生接口才能實現,因此只能寫成模塊。git
通常來講,都是調用模塊的功能,並不會依賴模塊返回值的,可是像 dom
模塊中的 getComponentRect
接口是用來計算組件的寬高和位置的,必須得從原生端獲取值。可是在 Weex 最初設計的版本里,模塊都是異步返回值的,也就是說,只能經過回調函數的方式拿到真正的佈局信息(也能夠本身封裝成 Promise)。如今 Weex 已經支持了模塊的同步返回值,可是爲了保持原先版本中接口的行爲一致,getComponentRect
這個方法依然是異步的。github
const dom = weex.requireModule('dom') const returns = dom.getComponentRect(this.$refs.box, option => { console.log(option) // { result: true, size: { ... } } }) console.log(returns) // undefined
上邊的代碼中,會先執行 console.log(returns)
再執行 console.log(option)
,而且 getComponentRect
方法沒有返回值,因此 returns
的值是 undefined,option
中才是真正的原生端返回的佈局信息。web
Weex 自己內置了不少模塊,出於通用性考慮,咱們只會把最基礎的模塊打包進 SDK。其餘個性化的模塊能夠本身來實現,或者從社區中找。Weex Market 將會是一個收集這些擴展模塊(組件、插件)的地方,結合 weex-pack 能夠實現方便的安裝和擴展。(目前來講,Weex Market 中仍是基於舊版 .we
語法的模塊比較多,不適用於 Vue,在使用前要看準適用的框架)vue-router
具體的擴展 Weex 模塊的方法,參考:
Weex 的運行環境有好幾種,在寫代碼的時候,有些狀況下須要獲取環境數據。Weex 提供了 weex.config
變量能夠獲取配置信息。
bundleUrl
: 當前 js bundle 的 URL 地址。
env
: 環境對象。
weexVersion
: WeexSDK 的版本。
appName
: 應用名字。
appVersion
: 應用版本。
platform
: 平臺信息,目前是 "iOS"
、"Android"
和 "Web"
之一。
osVersion
: 系統版本。
deviceModel
: 設備型號 (僅限 iOS 和 Android)。
deviceWidth
: 設備寬度。
deviceHeight
: 設備高度。
此外其實還有一個全局的 WXEnvironment
變量,它和 weex.config.env
的屬性是同樣的。
下邊是一個獲取環境數據的二維碼(支持拷貝):
由於在瀏覽器環境中,Vuex 是會自動註冊的,只須要引入庫文件就好了,若是重複註冊,Vuex 會拋出警告的。(下邊這段代碼摘自 Vuex)
// auto install in dist mode if (typeof window !== 'undefined' && window.Vue) { install(window.Vue) }
可是在 native 環境中沒有 window
變量,就須要再手動調用 Vue.use(Vuex)
註冊 Vuex 插件,在註冊前判斷當前運行的平臺。
import Vue from 'vue' import Vuex from 'vuex' // Vuex is auto installed on the web if (WXEnvironment.platform !== 'Web') { Vue.use(Vuex) }
若是你在不一樣端上運行了 weex-hackernews 裏的項目,會發如今瀏覽器上點擊文章連接是會新開一個頁籤的,可是在客戶端上點擊連接就不會新開視圖,而是在當前視圖裏跳轉。
這種不一樣的行爲體如今 story.vue 文件裏,這裏的跳轉連接並非直接使用的 Weex 裏的 <a>
標籤,而是自定義了一個 <external-link>
的組件,把 url
參數傳過去。
<external-link :url="story.url"> <text>{{story.title}}</text> <text v-if="story.url">({{ story.url | host }})</text> </external-link>
頁面跳轉邏輯是在 external-link.vue 裏組件實現的:
<template> <div @click="open"> <slot></slot> </div> </template> <script> export default { props: ['url'], methods: { open () { const env = weex.config.env || WXEnvironment // open a new window (tab) on the web if (env.platform === 'Web') { window.open(this.url) return } // change router path on native (Android & iOS) this.jump(`/article/${this.url}`) } } } </script>
該組件監聽了 click
事件,在點擊時會首先判斷當前運行的平臺,若是是 Web
,則使用 window.open
新開頁面,不然(在原平生臺中)就默認使用 vue-router
進行跳轉,這個「跳轉」其實只是更新了當前的視圖,其實還在同一個原生頁面內。
若是你看了 src/App.vue 中的代碼,會發現裏邊用了一個 androidback
的事件。它實現的效果是綁定了 Android 中的「返回」事件,點擊返回按鈕就會退回上一個視圖。
<template> <div @androidback="back"> <router-view></router-view> </div> </template> <script> export default { methods: { back () { this.$router.back() } } } </script>
這個事件並非 Vue.js 自己提供的,也不是 Web 標準裏的,在瀏覽器上確定不會給你提供一個以 android
開頭的事件名。在 vue-router
裏也不會加這樣的東西。甚至若是你去翻 Weex 的文檔,也找不到這個事件類型,它也不是 Weex 默認提供的。
想要實現 Android 特有的功能,就得在 Android 項目裏的代碼,在「前端」層面是解決不了這個問題的,要寫 java
。
首先,在 Android 裏確定是能夠監聽到「返回」按鈕的點擊事件的,其實只要實現 Activity
裏的 onBackPressed
接口就能夠了,它會在當前視圖裏點擊返回按鈕時執行。在 weex-hackernews Andorid 項目裏的 MainActivity.java 中,就實現了 onBackPressed
接口:
public void onBackPressed() { Log.e("USER ACTION", "BACK"); WXSDKManager.getInstance().fireEvent(mWXSDKInstance.getInstanceId(), "_root", "androidback"); }
在這個方法裏,經過 WXSDKManager.getInstance()
取到了當前頁面的實例,而後調用 fireEvent
接口給根視圖派發 androidback
事件,事件名是能夠自定義的。在 Weex Runtime 中會接收到這個事件,會傳遞給 Vue.js 框架,而且觸發最外層組件的 androidback
事件,最終會找到 back
方法並執行。(這裏說的 Weex Runtime 是前端代碼實現的,比 Vue.js 更底層一些)。
除了 Vue.js 自己的特性之外,Weex 還提供了不少平臺化的特性,這些特性比前端框架更底層,也更通用一些。即便你用的不是 Vue.js 而是 Rax,或者是舊版的 .we
的語法,Weex 裏的這些特性也都是能夠用的。
雖然同一份代碼能夠運行在三端,可是 iOS 和 Android 和 Web 都有各自的優點和缺陷,若是你想實現一些平臺特有的功能,Weex 也是支持的。若是你想要體現平臺特有的優點,就得針對某個平臺寫一下原生代碼。在寫 iOS 或者 Android 代碼的時候,確定能確保在其餘平臺中不會執行到;可是在寫 js 代碼的時候,若是使用了只在 Web 上纔有的特性,就得注意一些,不要讓 iOS 和 Android 執行到這些代碼。