系列文章的目录在 ? 这里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 执行到这些代码。