6.1 跳转到文章详情页面
    
   
6.1 跳转到文章详情页面
首先新建文章详情页面。在app.json的pages数组下新增页面路径:
“pages/post/post-detail/post-detail”
保存后,开发工具会自动生成post-detail页面的4个文件。首先要实现的是从post文章页面通过点击跳转到post-detail详情页面。
在post.wxml中的block代码块里注册一个事件。
    
     
      代码清单 6-1         注册跳转文章详情页面事件                                              post.wxml
     
    
   
<block wx:for="{{postList}}" wx:for-item="item" wx:for-index="idx">
<template catchtap="onTapToDetail"  is="postItemTpl" data="{{...item}}"/>
</block>以上代码仅仅在template上增加了一个catchtap。接着,在post.js中编写这个事件的响应函数onTapToDetail。
    
     
      代码清单  6-2   跳转文章详情页                                                        post.js
     
    
   
import{DBPost}from'../../db/DBPost.js';
Page({
    data:{ },
    onLoad:function(){
      var dbPost = new DBPost();
     
      this.setData({
        postList:dbPost.getAllPostData(),
        
        });
      },
      onTapToDetail(event){
          wx.navigateTo({
            url: 'post-detail/post-detail',
          })
      }
    
         
})
          
    添加完onTapToDetail函数后,保存运行,并在文章列表页面点击任意一篇文章。没有任何反应,页面也没有跳转。为什么会这样?
    
     6.2 不要在template上注册事件
    
   
6.2 不要在template上注册事件
那么在block标签上注册可以吗?来试试
同样不可以,因为block也会在编译后“消失”。
那么,我们只有在template的外部增加一个view,将template给包裹起来,并将catchtap事件注册到view组件上。
    
     
      代码清单   6-3      用view包裹template模板                                    post.wxml
     
    
    
   
<block wx:for="{{postList}}" wx:for-item="item" wx:for-index="idx">
<view   catchtap="onTapToDetail">
<template   is="postItemTpl" data="{{...item}}"/>
</view>
</block>保存后,点击5篇文章中的任意一篇,就可以正确地跳转到post-detail文章详情页面了。
    
     6.3 页面间传递参数的3种方式
    
   
6.3 页面间传递参数的3种方式
上一小节中,我们实现了从文章列表页面跳转到文章详情页面。要正确展示文章详情页面的内容,首先需要将文章的id号由post页面传递到post-detail页面,这样,post-detail页面才能知晓它要显示哪篇文章。
这涉及页面间的参数传递与通信。目前,在MINA框架中有以下几种参数传递方式:
- 
(1)使用全局变量(关于全局变量,本书后面的章节中会讲到)。 
- 
(2)使用缓存。 
- 
(3)通过页面导航url的query参数传递。 
基本上参数的传递只有以上3种方式,其他的比如像事件信号的传参方式(一个页面emit发送信号,一个页面on监听信号,这种在AngularJS里很常见的传参方式,小程序是不能天然支持的),其实都是这些基本思路的变种。
全局变量我们将在后面讲到,至于缓存的传参方式,开发者在学习完缓存后应该很容易想到。其实,使用缓存数据库存储data.js初始化数据,又在post.js中读取缓存数据,这其实就是页面间的参数传递。仔细想想,是不是这样?
(1)、(2)两种都涉及全局变量,笔者个人不推荐这种污染全局的传参方式,而且我们的需求仅仅是两个页面间传递参数,完全不需要干扰全局。所以,选用方法3来做页面间的参数传递。
6.3.1 组件的自定义属性
再来整理下思路。要将postId由post页面传递到post-detail页面,首先需要在post.js中获取到postId,随后再将postId附加到代码清单6-2中的wx.navigateTo的url中。
要想在post.js中获取到postId,就必须知道当前点击的文章是哪一篇文章。我们首先将postId绑定到每一篇文章的wxml中,使postId成为文章wxml的一个属性。注意,postId已在5.13小节中加入到data.js文件里。
绑定postId的方法很简单,就如同绑定文章的date、title等属性一样。post.js文件的代码无须任何改动,只需要对post.wxml文件做一下改动即可。
    
     
      代码清单     6-4      绑定postId                                  post.wxml
      
     
    
   
<block wx:for="{{postList}}" wx:for-item="item" wx:for-index="idx">
<view   catchtap="onTapToDetail"  post-data-id="{{postId}}">
<template   is="postItemTpl" data="{{...item}}"/>
</view>
</block>6.3.2 通过dataset获取组件自定义属性
修改post.js文件中的onTapToDetail函数如下:
    
     
      代码清单         6-5      获取post-item-id                         post.js
     
    
   
 onTapToDetail(event){
            var postId = event.currentTarget.dataset.postId;
            console.log("postId");
          wx.navigateTo({
            url: 'post-detail/post-detail?id='+postId,
          })
      }上述代码中,我们通过event.currentTarget.dataset.postId,这段代码成功地拿到了当前文章的postId。
event事件对象是由MINA框架在调用onTapToDetail函数时传递的参数。在event事件对象中,有一个currentTarget代表事件绑定的当前组件。
重点是dataset对象,dataset对象里包含当前组件中所有属性名以data-开头的自定义属性值。我们在代码清单6-5中的view上绑定了data-post-id,所以通过dataset.postId将可以拿到当前组件的postId。
组件自定义属性名有以下规则:
- 
必须以data-开头。 
- 
多个单词由连字符“-”链接。 
- 
单词中最好不要有大写字母,如果有大写字母,除单词第一个字母外,其余大写字母将被转化成小写。 
- 
在js中获取自定义属性值时,多个单词将被转化驼峰命名。 
看起来很复杂,但举几个例子就非常清楚了,如表6-1所示。
表6-1 组件的属性定义
     
   
在获取到postId后,我们将postId附加在导航Url的query参数中:
     
   
6.3.3 获取页面参数值
再来看看如何在post-detail页面中获取postId,在post-detail.js文件中添加以下代码:
    
     
      代码清单  6-6        获取页面参数                                             post-detail.js
      
     
    
   
// pages/post/post-detail/post-detail.js
Page({
    data:{},
    onLoad:function(options){
      var postId =  options.id,
    },
  
  }
)接受post页面传递参数的方法是通过post-detail页面onLoad函数里的options参数来获取。options参数是由框架传递的。
   注意,这里options.id中的“id”必须同代码清单6-6中navigateTo中url的query参数名称保持一致。比如,在query参数中使用的是name=postId,则这里要相应地使用options.id
   
   
    编译时设置初始化页面及参数
   
     6.4 编译时设置初始化页面及参数
    
   
   
现在我们主要的代码编辑工作集中在post-detail这个页面。但每当保存刷新小程序后,项目都将从欢迎页面启动。我们不得不依次点击启动页面、文章列表,才能进入到文章详情页面以预览文章详情的效果,这相当的麻烦。
当然可以按照4.1小节中的方法,将post-detail页面设置为app.json中pages数组的第一项,但post-detail还需要传入一个postId的参数才可以正确地运行,且手动来回更改pages数组非常麻烦。
小程序在122100版本中增加了编译选项,在此版本中,官方提供了一个“自定义编译”功能,可用于定义小程序的启动页面,如图6-3所示。
122100版本后,“编译”这里变成了两个选项,请仔细查看。上面一个图标是默认编译,下面的图标是自定义编译,点击下面的图片将弹出如图6-4所示的界面。
     
   
图6-4 自定义编译选项
启动页面一栏中将路径设置为post-detail页面的启动路径:
pages/post/post-detail/post-detail
页面自定义参数类似于url中的query参数,设置id=2将可以在页面中通过onLoad函数中的options.id获取到这个值。
设置完成后,必须勾选【使用以上条件编译】这个选项。
保存刷新页面,项目将直接进入post-detail页面,不再出现welcome启动页。同时,我们发现,以这种方式打开的post-detail页面无法再返回到post页面,因为不是通过post页面导航到post-detail页面的。
可以通过“&”连接多个页面参数,比如id=2&name=”MR.L”,同时将两个参数传递到post-detail页面中。
有了以上功能,就可以非常方便地调试post-detail页面。
如果想恢复默认的启动页,只需去掉【使用以上条件编译】选项即可。
 
