最近用微信小程序做了一个电影类APP,业务逻辑不难,但在做最后一个页面时遇到了一个诡异的问题,这个问题让我对小程序框架里的事件和数据绑定有了更深的认识。
问题是这样的:
该小程序有4个页面,分别是“影院热映home”、“即将上映comingSoon”、“电影查询search”和点击以上3个页面中每条具体的电影条目会跳转到的“详情页面detail”。
这个问题刚好出在从“影院热映”点击电影条目到“详情页面”处,要么无法显示电影具体信息,要么点击不同条目总是显示同一条电影的信息。
因为从不同页面点击电影条目,绑定的点击事件都会将页面跳转到对应详情页面,而详情页面的detail.wxml文件是确定的。那么无法正确显示电影信息,一定是detail.wxml文件绑定的数据出问题了。
所以从detail.wxml的数据来源即detail.js找问题。
// pages/detail/detail.js
var subjectUtil = require("../../utils/subjectUtil.js");
Page({
data:{
movie:{}
},
onLoad:function(options){
// 页面初始化 options为页面跳转所带来的参数
this.loadMovie(options.id);
console.log(options);
},
loadMovie: function(id) {
wx.showToast({
title: '加载中',
icon: 'loading',
duration: 10000
});
var page = this;
//var id = wx.getStorageSync('id');
wx.request({
url: 'https://api.douban.com/v2/movie/subject/'+id,//需要传递具体的id才能加载电影;
header: {
'Content-type': 'json'
},
success: function(res){
var subject=res.data;//
subjectUtil.processSubject(subject);
page.setData({movie:subject});
},
complete:function(e) {
wx.hideToast();
}
});
},
})
wx.request()是微信小程序自带的发起HTTPS网络请求的API,我所需的资源从url: ‘https://api.douban.com/v2/movie/subject/‘+id 获取,这个API接口带一个id参数,不同的电影有不同的id。所以详情页出问题代表数据源出问题,数据源出问题代表id出问题,现在的关键是看id出什么问题。
要想了解id的问题,首先要知道id在哪里,其次知道点击电影条目之后怎么到详情页面去的。
从API接口请求回来的资源是一个对象,对象里有大量的数据,比如图片、评分等,id就是其中一个。
好了,已经知道id的位置,那这个id又是怎么到detail.js中去的呢?
其实,这个id是绑定到任何一个页面的WXML里的。
<!--movieTpl.wxml-->
<template name="movies">
<block wx:for="{{movies}}">
<view class="movie" bindtap="detail" id="{{item.id}}">
<view class="pic">
<image src="{{item.images.medium}}" mode="aspectFit" />
</view>
<view class="movie-info">
<view class="base-info">
<text>{{item.basicInfo}}</text>
</view>
</view>
</view>
<view class="hr"></view>
</block>
</template>
<view class="movie" bindtap="detail" id="{{item.id}}">这段代码里id这个属性绑定的值{{item.id}}就是某一条电影的id。
所以电影的id一开始就应该存在于对应页面的wxml代码里,比如存在于home.wxml里。
上面这段代码里的bindtap=”detail”代表一个点击事件,在页面上点击view组件后,会激活对应js文件里的detail函数,并跳转到detail页面。
//home.js
detail:function(e) {//点击事件e为参数
wx.navigateTo({
url: '../detail/detail',
})
}
function(e)里的参数e是点击对应组件后返回的事件处理函数的参数,这个参数类型是object,里面有一个currentTarget的对象,这个对象有个属性id,这个id表示当前组件的id,用 e.currentTarget.id就可以得到当前组件的id。还记得吗,组件的id被赋值为{{item.id}},此处的item表示列表渲染时,每一个数组元素的值,这个值就是某部电影对象的详细信息,{{item.id}}表示某部电影的id。也就是详情页面通过API接口获得信息需要的id。
到现在为止,id仍然只在“影院热映”这个页面里,需要这个id的是详情页面,那怎么才能把id传递到详情页面里去呢?
有两种方法:
- 利用缓存,在home.js缓存id,然后从detail.js处取出。
- 利用页面跳转带去参数
这里以方法1为例。
//home.js
detail:function(e) {//点击事件e为参数
wx.setStorageSync('id', e.currentTarget.id)
wx.navigateTo({
url: '../detail/detail',
})
}
wx.setStorageSync()之后,id就存到了本地,detail.js从本地取出来使用即可。
loadMovie: function() {
var page = this;
var id = wx.getStorageSync('id');
wx.request({
url: 'https://api.douban.com/v2/movie/subject/'+id,//需要传递具体的id才能加载电影;
header: {
'Content-type': 'json'
},
success: function(res){
var subject=res.data;//
subjectUtil.processSubject(subject);
page.setData({movie:subject});
},
complete:function(e) {
wx.hideToast();
}
});```
好了,到现在为止,已经明白了点击组件跳转到电影详情这个功能背后的id是如何传递的了。
那么回到最开始,为什么我在点击home页面时,detail页面会出错呢?因为我同时使用了两种传递id的办法,而且将detail: function(e){}作为全局函数写在app.js供其他页面引用的时候因为粗心大意出了问题,不过这个问题也让我对微信MINA框架里的数据缓存有了进一步的理解。要把这个问题讲明白还需要一些图片和代码,下一篇文章再总结吧。