5 页面详情页
5.1跳转到文章详情页面
首先新建文章详情页面。在app.json的pages数组下新增页面路径:
"pages/post/post-detail/post-detail"保存后,开发工具会自动生成post-detail页面的4个文件。
-首先要实现的是从post文章页面通过点击跳转到post-detail详情页面。
在post.wxml中的block代码块里注册一个事件。<template catchtap="onTapToDetail" is="postItemTpl" data="{{...item}}">
以上代码仅仅在template上增加了一个catchtap。接着,在post.js中编写这个事件的响应函数onTapToDetail。
onTapToDetail(event){
wx.navigateTo({
url: 'post-detail/post-detail',
})
},
添加完onTapToDetail函数后,保存运行,并在文章列表页面点击任意一篇文章。没有任何反应,页面也没有跳转:template标签仅仅是一个占位符,在编译后会被template的模板内容替换。所以,在template上注册事件是无效的。
同样在block标签上注册不可以,因为block也会在编译后“消失”。只有在template的外部增加一个view,将template给包裹起来,并将catchtap事件注册到view组件上。
<view catchtap="onTapToDetail" data-post-id="{{item.postId}}">
在post.js中编写事件的响应函数onTapToDetail
onTapToDetail(event){
wx.navigateTo({
url: 'post-detail/post-detail,
})
}
保存后,点击5篇文章中的任意一篇,就可以正确地跳转到post-detail文章详情页面了。
5.2 页面间传递参数的三种形式
- 目前,在MINA框架中有以下几种参数传递方式:
(1)使用全局变量(关于全局变量,本书后面的章节中会讲到)。
(2)使用缓存。
(3)通过页面导航url的query参数传递。【使用缓存数据库存储data.js初始化数据,又在post.js中读取缓存数据,这其实就是页面间的参数传递。】
基本上参数的传递只有以上3种方式,其他的比如像事件信号的传参方式(一个页面emit发送信号,一个页面on监听信号,这种在AngularJS里很常见的传参方式,小程序是不能天然支持的),其实都是这些基本思路的变种。
5.2.1 组建的自定义属性
要将postId由post页面传递到post-detail页面,首先需要在post.js中获取到postId,随后再将postId附加到代码清单6-2中的wx.navigateTo的url中。
要想在post.js中获取到postId,就必须知道当前点击的文章是哪一篇文章。我们首先将postId绑定到每一篇文章的wxml中,使postId成为文章wxml的一个属性。
绑定postId的方法很简单,就如同绑定文章的date、title等属性一样。post.js文件的代码无须任何改动,只需要对post.wxml文件做一下改动即可。
<view catchtap="onTapToDetail" data-post-id="{{item.postId}}">
<template is="postItemTpl" data="{{...item}}"></template>
</view>
以上代码中,我们在view里增加了一个属性data-post-id="{{item.postId}}",保存并运行代码后,打开调试中的【Wxml】这个面板,文章页面的骨架如图
图6-2 将postId绑定在单篇文章的view容器上,明显地看到,每篇文章的id号都被绑定在了该文章的view容器上,剩下的工作就是,如何在post.js中获取当前点击的文章的id号。
5.2.2 通过dataset属性获取组件定义属性
修改post.js文件中的onTapToDetail函数如下:
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。
-组件自定义属性名有以下规则:
(1)必须以data-开头。
(2)多个单词由连字符“-”链接。
(3)单词中最好不要有大写字母,如果有大写字母,除单词第一个字母外,其余大写字母将被转化成小写。
(4)在js中获取自定义属性值时,多个单词将被转化驼峰命名。
5.2.3 获取页面参数值
再来看看如何在post-detail页面中获取postId,在post-detail.js文件中添加以下代码:
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。
5.3 编译时设置初始化页面以及参数
设置启动页面,避免每次都从主页进入
5.4 读取文章详细数据
需要根据这个postId去缓存数据库中读取文章详细数据,并将数据用于构建文章详情页面。
所有对于缓存数据库的操作,我们都会放在DBPost这个对象中,在DBPost.js中增加和修改部分代码。
class DBPost{
constructor(postId){
this.storageKeyName="postList";
this.postId=postId;
} //获取所有页面信息
getAllPostData(){
var res =
wx.getStorageSync(this.storageKeyName);
if(!res){
res = require("../data/data.js").postList; this.initPostList(res);
}
return res;
} //本地缓存 保留/更新
execSetStorageSync(data){
wx.setStorageSync(this.storageKeyName,data)
}
//获取指定id号的文章数据 getPostItemById(){
var postsData = this.getAllPostData();
var len = postsData.length;
for(var i=0; i<len; i++){
if(postsData[i].postId == this.postId){
return{
index: i,
data: postsData[i]
};
}
}
}};
export{DBPost}
首先修改constructor构造函数,增加一个构造参数postId,并将postId保存到this变量中。
接着增加一个方法getPostItemById用于获取指定id号的文章数据。
DBPost修改完毕后,我们尝试在post-detail.js中获取指定id号的文章数据,并使用this.setData绑定该数据。
onLoad: function (options) {
var postId = options.id;
this.dbPost = new DBPost(postId);
this.postData = this.dbPost.getPostItemById().data;
this.setData({
post:this.postData
})
},
注意上述代码中,在使用new实例化DBPost后,将dbPost这个对象保存在了变量this中,这样以后如果要再次使用DBPost,则不需要再重新实例化这个对象,只需要使用this.dbPost即可引用这个对象。
5.5 文章id号的数据流向图
文章id号最初是存在于data.js中的,通过一系列的事件操作,它最终会被传递到post-detail.js中。一旦post-detail.js拿到文章的id号,该页面就可以根据id号来获取文章详情数据了。
5.6 动态设置导航栏标题
5.6.1 使用配置配置导航栏标题
第一种方法是使用app.json或者页面的json文件来配置导航栏标题。如果是在app.json中进行配置,则它是全局行为,项目所有的页面将显示同一个标题;而如果是在页面的json文件中配置标题,则只会影响当前配置页面。
之前在app.json的window属性中通过设置navigationBarBackgroundColor实现了指定导航栏的颜色。window还有以下2个属性用于配置导航栏文本:
• navigationBarTextStyle 指定导航栏标题文字的颜色,只支持black/white,默认值为black。
• navigationBarTitleText 指定导航栏标题文字。
在app.json中对window属性增加以上两个配置项,代码如下:
"window": {
"navigationBarBackgroundColor": "#ECC0A8",
"backgroundColor": "#FFFF",
"navigationBarTitleText": "测试之旅",
"enablePullDownRefresh": true },
保存运行后可以看到,所有页面的导航栏都增加了“文字”这两个字,它的颜色为白色。
- window这个配置项既可以在app.json中配置,也可以在window中配置(其他配置项只能在app.json中配置)。
删除上述代码的navigationBarTextStyle和navigationBarTitleText,在post.json文件中加入以下代码:
{
"navigationBarTitleText": "详情界面"
}
这样,导航栏文字就只会在post页面中出现了。
6.9.2 使用wx.setNavigationBarTitle(OBJECT)设置导航条
在某些情况下,我们希望导航栏的文字可以根据页面内容的不同而有所变化。比如在文章详情页面中,我们希望导航栏可以实时显示当前文章的标题,不同的文章显示不同的标题文字。来看看如何实现这个功能。
小程序提供了wx.setNavigationBarTitle(OBJECT)来动态设置导航栏标题。小程序官方文档中指出,页面的导航栏标题必须在页面生命周期的onReady之后来设置,否则无效。原文如下:
对界面的设置如wx.setNavigationBarTitle请在onReady之后设置。
我们遵照官方文档的说明,在post-detail.js中加入以下代码:
onReady:function(){
wx.setNavigationBarTitle({
title: this .postData.title
})
},
按照文档的描述,我们在页面生命周期函数onReady中调用了wx.setNavigation-BarTitle(object)方法。它接收一个object参数,其中title属性被设置为当前文章的标题。
保存运行代码,发现页面的导航栏文字变成了文章的标题。