第六篇 导航、页面跳转、stream、webview

在一款应用中,导航、页面切换、获取网络数据是很常见的功能。因此,本节做一个简单的介绍。

wxc-navpage组件

什么是navigation?如下图:
6. 导航、页面跳转、stream、webview - 图1
在iOS,使用的控制是UINavigationController。我们可以看到Navigation的内容比较多,例如中间的标题、左侧的搜索图片、右侧的图片等。同样,Weex也提供了该组件,那就是wxc-navpage。

  1. <template>
  2. <wxc-navpage height={% raw %}{{...}}{% endraw %} background-color="..." title="..." title-color="..." left-item-title="..." left-item-color="..." right-item-src="...">
  3. <content> ...</content>
  4. </wxc-navpage>
  5. </template>
  6. <script>
  7. require('weex-components');
  8. module.exports = {
  9. created: function() {
  10. this.$on('naviBar.rightItem.click',function(e){
  11. //handle your click event here.
  12. });
  13. this.$on('naviBar.leftItem.click',function(e){
  14. //handle your click event here.
  15. });
  16. }
  17. }
  18. </script>

我们,可以看到 wxc-navpage不仅支持基础的样式,同样提供了 title、title-color、 left-item-title、left-item-color、right-item-src等等属性,这里可以参考http://alibaba.github.io/weex/doc/components/wxc-navpage.html

wxc-navpage内嵌子组件,即<content> ...</content>。但是,我们改造上面的片段代码是跑不起来的。因此我们需要安装weex-components:

  1. $ npm install weex-components

weex-components中包含的内容比较多,例如也提供了wxc-tabbar组件。但是,需求是多样的。有时候,发现weex-components组件不能满足一些特定的需求。那么,这里提供2个思路:(1)给weex提issues,让weex支持新的需求 (2)如果实在等不及,可以将weex-components从node_modules中拷贝出来,然后修改里面的内容。

页面跳转

很可能一个应用需要多个页面,那么多个页面如何跳转呢?其实Weex的Demo就给出了很好的例子。例如,这里的代码如下:

  1. var bundleUrl = this.$getConfig().bundleUrl;
  2. bundleUrl = new String(bundleUrl);
  3. console.log('hit', bundleUrl);
  4. var nativeBase;
  5. var isAndroidAssets = bundleUrl.indexOf('file://assets/') >= 0;
  6. var isiOSAssets = bundleUrl.indexOf('file:///') >= 0 && bundleUrl.indexOf('WeexDemo.app') > 0;
  7. if (isAndroidAssets) {
  8. nativeBase = 'file://assets/';
  9. }
  10. else if (isiOSAssets) {
  11. // file:///var/mobile/Containers/Bundle/Application/{id}/WeexDemo.app/
  12. // file:///Users/{user}/Library/Developer/CoreSimulator/Devices/{id}/data/Containers/Bundle/Application/{id}/WeexDemo.app/
  13. nativeBase = bundleUrl.substring(0, bundleUrl.lastIndexOf('/') + 1);
  14. }
  15. else {
  16. var host = 'localhost:12580';
  17. var matches = /\/\/([^\/]+?)\//.exec(this.$getConfig().bundleUrl);
  18. if (matches && matches.length >= 2) {
  19. host = matches[1];
  20. }
  21. nativeBase = 'http://' + host + '/' + this.dir + '/build/';
  22. }
  23. var h5Base = './index.html?page=./' + this.dir + '/build/';
  24. // in Native
  25. var base = nativeBase;
  26. if (typeof window === 'object') {
  27. // in Browser or WebView
  28. base = h5Base;
  29. }
  30. this.baseURL = base;

上面的代码是我从Weex Demo中拔出来的。这一块也是经常被开发者问到的,就是跳转路径的问题。其实,仔细看上面的代码,我们只需要关注两个地方,一个是this.dir,另一个是var h5Base = './index.html?page=./'
我们在created方法中获取到this.dir。this.dir 则是我们打包完成的js bundle的目录。h5Base则是web端的路径。它的基本形式是:

  1. http://127.0.0.1:8080/index.html?page=./dist/index.js

其中index.html则是web端运行的载体,page=./dist/index.js则是传入到weex init中的参数。我们一般在集成web时候,会写上如下代码:

  1. (function () {
  2. function getUrlParam (key) {
  3. var reg = new RegExp('[?|&]' + key + '=([^&]+)')
  4. var match = location.search.match(reg)
  5. return match && match[1]
  6. }
  7. var loader = getUrlParam('loader') || 'xhr'
  8. var page = getUrlParam('page') || 'examples/build/index.js'
  9. // jsonp callback name should be specified or be the default
  10. // value 'weexJsonpCallback' if the 'jsonp' loader is used.
  11. var JSONP_CALLBACK_NAME = 'weexJsonpCallback'
  12. window.weex.init({
  13. jsonpCallback: JSONP_CALLBACK_NAME,
  14. appId: location.href,
  15. loader: loader,
  16. source: page,
  17. rootId: 'weex',
  18. downgrade: [] // 'list', 'scroller'
  19. })
  20. })();

getUrlParam就是获取url中的参数。如果页面有page参数,我们则调用page参数对应的js文件的代码。
到这里,基本上,可以看出跳转路径了。那么使用什么API跳转呢?那就是navigator。

  1. var url = this.recommend[index].url;
  2. var title = this.recommend[index].title;
  3. var navigator = require('@weex-module/navigator');
  4. var params = {
  5. 'url': this.baseURL + 'yywebview.js?weixin_title=' + title + '&weixin_url=' + url,
  6. 'animated' : 'true',
  7. }
  8. console.log('------',params.url);
  9. navigator.push(params, function(e) {});

我们获取到this.baseUR,然后拼接路径。this.baseUR则是created方法中获取到不同端的路径前缀。这里,引入了navigator = require('@weex-module/navigator');组件,然后使用了push方法,将路由对象添加进了路由栈。如果我们需要回退到上一个视图,该如何呢?其实navigator api已经提供了该功能,那就是pop。具体可以参考http://alibaba.github.io/weex/doc/modules/navigator.html

网络请求

Weex提供了网络请求模块,那就是stream。简单的例子如下:

  1. stream.fetch({
  2. method: 'GET',
  3. url: "http://httpbin.org/get",
  4. type:'json'
  5. }, function(response) {
  6. //process response
  7. },function(response){
  8. //progress response
  9. console.log("current bytes received:"+response.length);
  10. });

基本上stream.fetch方法的几个参数都很容易理解。如果需要POST、PUT、DELETE等。可以参考: https://github.com/alibaba/weex/blob/dev/examples/module/stream-demo.we

webview

当然,在Weex中也支持Webview类似组件,只是Weex命名其为web。具体使用如下:

  1. <template>
  2. <div class="wrapper">
  3. <web class="web" src="{{src}}" style="height:{{height}};" onpagestart="pagestart" onpagefinish="pagefinish" onerror="error"></web>
  4. </div>
  5. </template>
  6. <style>
  7. .text{
  8. font-size:26;
  9. }
  10. .web{
  11. flex:1;
  12. }
  13. </style>

其中src就是我们要打开的网页地址。onpagestart、onpagefinish、onerror几个事件很重要。比如在onpagefinish时去掉loading,onerror时给用户友好提示。 具体参考:http://alibaba.github.io/weex/doc/components/web.html