背景
周末,有空正在处理一个简单的需求:有两个按钮,第一个按钮点完之后跳转到一个新的页面,第二个按钮点完之后也跳转到一个新的页面,这两个新的页面只有一个文本不同。按钮存在的页面和两个新的页面都是WEEX写的。那么自然而然大家想到的就是写两个页面,一个页面承载两个按钮,另一个页面根据第一个页面的传参决定是展示哪个文本,下面看看如何实现这个事情。
基础知识
WEEX页面间跳转
首先我们应该实现第一个功能:点完一个按钮实现页面间的跳转。那么跳转这件事情WEEX一共有两种方式:navigatior和vue-router;
navigatior
navigator 模块就是用来实现iOS navigation controller类似的效果的。使用方式也简单:
压入导航堆栈
var navigator = weex.requireModule('navigator')
navigator.push({
url: '',
animated: "true"
}, event => {
//执行完该操作后的回调
})
弹出导航堆栈
var navigator = weex.requireModule('navigator')
navigator.pop({
animated: "true"
}, event => {
//执行完该操作后的回调
})
vue-router
vue-router 是专为 Vue.js 开发的便于实现单页应用的工具库,然而移动端没有浏览器的 History API,也不存在 DOM,因此如果想在 Weex 环境中使用 vue-router ,有些功能受到了限制,例如weex在移动端原生环境中强制使用vue-router的abstract 模式,使用时应该注意。
实现的主要方式是通过主动调用 router 实例上的 push 方法实现跳转
<script>
import router from './path/to/router'
export default {
methods: {
jump () {
router.push('profile')
}
}
}
</script>
WEEX页面间通信
通信有两种方式:一种是通过跳转链接带参数的方式、一种是通过BroadcastChannel。
跳转链接带参数的方式
这种方式下我们只需要将参数拼成符合ABNF语义的格式,在第二个页面解析即可:
在A 页面
this.testPath = url + 'xxx.js?a=b'
navigator.push({
url: this.testPath,
animated: "true"
}, event => {
});
在B页面
var str = weex.config.bundleUrl; //取得整个地址栏
var num = str.indexOf("?");
str = str.substr(num + 1); //取得所有参数
之后按照我们自己的需求对参数进行分割使用即可。
BroadcastChannel
BroadcastChannel 是 W3C 规范中的一部分,需要的同学可以了解下
BroadcastChannel 接口的定义如下:
declare interface BroadcastChannel = {
name: string,
postMessage: (message: any) => void;
onmessage: (event: MessageEvent) => void;
close: () => void;
}
name: 监听的频道名称,用来区分不同的频道(跨频道不可通信)。
postMessage: 用于在当前频道中广播消息。
onmessage: 消息事件的处理函数。在频道中接收到广播消息之后,会给所有订阅者派发消 息事件。
close: 关闭当前频道。
实践
有了上边的基础,我们来看看BroadcastChannel实现通信的实际方法
在A页面中:
const Steve = new BroadcastChannel('Avengers')
Steve.postMessage('Assemble!')
在B页面中:
const Stark = new BroadcastChannel('Avengers')
Stark.onmessage = function (event) {
console.log(event.data) // 注意这句
}
例子的注意事项
首先,如果你在网上找,那么所有的例子在消息的处理函数中都是做一些console的语句。这是为什么?可不可以对dom进行改变? 例如可不可以进行
this.prop = a
这样的操作
不可以。原因是在消息处理函数里,this是作为值传递的, 即使你操作了,也不会影响页面本身对应的this。
大家都见过值传递和引用传递的区别吧,这就是为什么例子的处理函数里都只举console.log的原因。
其他导致不成功的原因
有时候,正在测试、发现页面的元素不显示了:那么请检查:
- 是否对元素添加了width的css。
- 单位是否是px (weex只支持这一种单位)
- flex的值是否是1 , 1和auto的效果并不相等。(例如对于<web>组件)
总结
页面间的通信如果简单或者并不是页面创建时就能确定参数值的情况就直接使用broadcastChannel。其他情况使用链接带参数的方式进行通信。最近两周在做需求(好吧这只是个借口)所以偷懒了,希望大家遇到问题能从这里得到一点帮助。