搜索页面、更多页面、电影详情页面
功能
搜索页面:实现点击搜索框,弹出搜索的电影结果
更多页面:点击电影页面的更多按钮,显示对应模块的更多电影
电影详情页面:点击对应的电影,进入对应的电影详情页面
搜索页面
movies.json
新增 l-search-bar组件
{
"usingComponents": {
"movie-list":"/components/movie-list/index",
"movie":"/components/movie/index",
"l-search-bar":"/miniprogram_npm/lin-ui/search-bar/index"
}
}
movies.wxml
l-search-bar绑定两个事件:点击确认按钮触发onConfirm事件,显示对应的搜索结果,这里用到了之前实现的组件movie;取消时触发onSearchCancel,显示原始页面,这里用wx:if/wx:else实现页面显示的切换。
<!--pages/movies/movies.wxml-->
<l-search-bar bind:lincancel="onSearchCancel" bind:linconfirm="onConfirm" l-class="ex-search-bar"
placeholder="盗梦空间、你的名字" />
<view wx:if="{{!searchResult}}">
<movie-list bind:tap="onGotoMore" data-type="in_theaters" movies="{{inTheaters}}" title="正在热映" f-class="movie-list" />
<movie-list bind:tap="onGotoMore" data-type="coming_soon" movies="{{comingSoon}}" title="即将上映" f-class="movie-list" />
<movie-list bind:tap="onGotoMore" data-type="top250" movies="{{top250}}" title="豆瓣Top250" f-class="movie-list" />
</view>
<view class="search-container" wx:else>
<block wx:for="{{searchData}}" wx:key="index">
<movie class="movie" movie="{{item}}" />
</block>
</view>
movies.js
// pages/movies/movies.js
const app = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
inTheaters:[],
comingSoon:[],
top250:[],
searchResult:false,
searchData:[]
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
console.log(app)
wx.request({
url:app.globalData.gBaseUrl+'in_theaters?',
data:{
start:0,
count:3
},
success:(res)=>{
console.log(res);
console.log("this",this)
this.setData({
inTheaters:res.data.subjects
})
console.log("inTheaters",this.data.inTheaters);
}
})
wx.request({
url: app.globalData.gBaseUrl+'coming_soon?',
data:{
start:0,
count:3
},
success:(res)=>{
this.setData({
comingSoon:res.data.subjects
})
}
})
wx.request({
url: app.globalData.gBaseUrl+'top250?',
data:{
start:0,
count:3
},
success:(res)=>{
this.setData({
top250:res.data.subjects
})
}
})
},
onGotoMore(events){
console.log("onGotoMore");
console.log(events);
const type = events.currentTarget.dataset.type;
wx.navigateTo({
url: '/pages/more-movie/more-movie?type='+type,
})
},
onConfirm(events){
this.setData({
searchResult:true
});
wx.request({
url: app.globalData.gBaseUrl + 'search',
data:{
q:events.detail.value
},
success:(res)=>{
console.log("onConfirm");
console.log(res);
this.setData({
searchData:res.data.subjects
})
}
})
},
onSearchCancel(events){
this.setData({
searchResult:false
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
更多页面
功能解析
1、因为电影页面有3个模块,点击对应的更多按钮,跳转到对应的过呢更多电影页面
2、跳转到更多页面时,这里每个电影可以复用之前实现的movie组件
3、首次加载12部电影,往下拉时,再加载12部电影
4、向上拉重新加载页面,加载最新的12部电影
more-movie.json
{
"usingComponents": {
"l-rate":"/miniprogram_npm/lin-ui/rate/index"
}
}
more-movie.wxml
<!--pages/more-movie/more-movie.wxml-->
<view class="container">
<block wx:for="{{movies}}" wx:key="index">
<movie class="movie" movie="{{item}}"></movie>
</block>
</view>
more-movie.wxss
/* pages/more-movie/more-movie.wxss */
.container{
display: flex;
flex-direction: row;
flex-wrap: wrap;
padding:30rpx 28rpx;
justify-content: space-between;
}
.movie{
margin-bottom: 30rpx;
}
实现每行3个movie,间隔相同
justify-content: space-between;
more-movie.js
在onLoad时解析从movie.wxml中传入的data-type属性对应的值,实现加载对应模块的更多电影的数据,这个值在options.type中接收到。
当触及底部时,触发onReachBottom方法,这里将原来获取到的movies数据使用concat拼贴新申请到的电影数据。
// pages/more-movie/more-movie.js
const app = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
movies:[],
_type:""
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
console.log("more-movie的onload");
console.log(options);
const type = options.type;
this.data._type = type;
wx.request({
url: app.globalData.gBaseUrl+type,
data:{
start:0,
count:12
},
success:(res)=>{
console.log(res)
this.setData({
movies:res.data.subjects
})
}
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
console.log("more-movie page onPullDownRefresh");
wx.request({
url: app.globalData.gBaseUrl+this.data._type,
data:{
start:0,
count:12
},
success:(res)=>{
this.setData({
movies:res.data.subjects
})
}
})
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
//每触底一次,加载新的数据
console.log("more-movie page onReachBottom");
wx.request({
url: app.globalData.gBaseUrl+this.data._type,
data:{
start:this.data.movies.length,
count:12
},
success:(res)=>{
console.log(res);
this.setData({
movies:this.data.movies.concat(res.data.subjects)
})
}
})
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
电影详情页面
这个页面主要涉及电影详情页面的css样式,然后import了util.js里的方法,进行电影数据的处理。
movie-detail.json
{
"usingComponents": {
"l-rate":"/miniprogram_npm/lin-ui/rate/index"
}
}
movie-detail.wxml
<!--pages/movie-detail/movie-detail.wxml-->
<view class="container">
<image mode="aspectFill" class="head-img" src="{{movie.image}}"></image>
<view class="head-img-hover">
<text class="main-title">{{movie.title}}</text>
<text class="sub-title">{{movie.subtitle}}</text>
<view class="like">
<text class="highlight-font">{{movie.wishCount}}</text>
<text class="plain-font">人喜欢</text>
<text class="highlight-font">{{movie.commentsCount}}</text>
<text class="plain-font">条评论</text>
</view>
<image bind:tap="onViewPost" class="movie-img" src="{{movie.image}}"></image>
</view>
<view class="summary">
<view class="original-title">
<text>{{movie.title}}</text>
</view>
<view class="flex-row">
<text class="mark">评分</text>
<view class="score-container">
<l-rate disabled="{{true}}" size="22" score="{{movie.rating}}" />
<text class="average">{{movie.average}}</text>
</view>
</view>
<view class="flex-row">
<text class="mark">导演</text>
<text>{{movie.directors}}</text>
</view>
<view class="flex-row">
<text class="mark">影人</text>
<text>{{movie.casts}}</text>
</view>
<view class="flex-row">
<text class="mark">类型</text>
<text>{{movie.genres}}</text>
</view>
</view>
<view class="hr"></view>
<view class="synopsis">
<text class="synopsis-font">剧情简介</text>
<text class="summary-content">{{movie.summary}}</text>
</view>
<view class="hr"></view>
<view class="casts">
<text class="cast-font"> 影人</text>
<scroll-view enable-flex scroll-x class="casts-container">
<block wx:for="{{movie.castsInfo}}" wx:key="index">
<view class="cast-container">
<image class="cast-img" src="{{item.img}}"></image>
<text>{{item.name}}</text>
</view>
</block>
</scroll-view>
</view>
</view>
movie-detail.wxss
/* pages/movie-detail/movie-detail.wxss */
.container{
display: flex;
flex-direction: column;
}
.head-img{
width: 100%;
height: 320rpx;
-webkit-filter:blur(20px);
filter:blur(20px);
}
.head-img-hover{
width: 100%;
height: 320rpx;
position: absolute;
display: flex;
flex-direction: column;
}
.main-title{
font-size: 38rpx;
color:#fff;
font-weight: bold;
letter-spacing: 2rpx;
margin-top: 50rpx;
margin-left: 40rpx;
}
.sub-title{
font-size: 28rpx;
color:#fff;
margin-left: 40rpx;
margin-top: 30rpx;
}
.like{
margin-top: 30rpx;
margin-left:40rpx;
}
.highlight-font{
color: #f21146;
font-size: 22rpx;
margin-right: 10rpx;
}
.plain-font{
color:#666;
font-size: 22rpx;
margin-right: 30rpx;
}
.movie-img{
height: 238rpx;
width: 175rpx;
position: absolute;
top:160rpx;
right: 30rpx;
}
.summary{
margin-left: 40rpx;
margin-top: 40rpx;
columns: #777777;
}
.original-title{
color:#1f3463;
font-size: 24rpx;
font-weight: bold;
margin-bottom: 40rpx;
}
.flex-row{
display: flex;
flex-direction: row;
align-items: baseline;
margin-bottom: 10rpx;
}
.mark{
margin-right: 30rpx;
white-space: nowrap;
color: #999999;
}
.score-containe{
display: flex;
flex-direction: row;
align-items: baseline;
}
.average{
margin-left: 20rpx;
margin-top: 4rpx;
}
.hr{
margin-top:45rpx;
width: 100%;
height: 1px;
background-color: #d9d9d9;
}
.synopsis{
margin-left:40rpx;
display:flex;
flex-direction: column;
margin-top: 50rpx;
}
.synopsis-font{
color:#999;
}
.summary-content{
margin-top: 20rpx;
margin-right: 40rpx;
line-height:40rpx;
letter-spacing: 1px;
}
.casts{
display: flex;
flex-direction: column;
margin-top:50rpx;
margin-left:40rpx;
}
.cast-font{
color: #999;
margin-bottom: 40rpx;
}
.cast-img{
width: 170rpx;
height: 210rpx;
margin-bottom: 10rpx;
}
.casts-container{
display: flex;
flex-direction: row;
margin-bottom: 50rpx;
margin-right: 40rpx;
height: 300rpx;
}
.cast-container{
display: flex;
flex-direction: column;
align-items: center;
margin-right: 40rpx;
}
// pages/movie-detail/movie-detail.js
import {convertToCastString, convertToCastInfos} from '../../utils/util.js'
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
const mid = options.mid;
wx.request({
url: app.globalData.gBaseUrl+'subject/' + mid,
success:(res)=>{
console.log(res.data);
this.processMovieData(res.data);
}
})
},
processMovieData(movie){
const data = {}
data.directors = convertToCastString(movie.directors)
data.casts = convertToCastString(movie.casts)
data.image = movie.images.large
data.title = movie.title
data.subtitle = movie.countries[0]+'·'+movie.year
data.wishCount = movie.wish_count
data.commentsCount = movie.comments_count
data.rating = movie.rating.stars/10
data.average = movie.rating.average
data.genres = movie.genres.join('、')
data.summary = movie.summary
data.castsInfo = convertToCastInfos(movie.casts)
this.setData({
movie:data
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
util.js
function convertToCastString(casts){
var castsjoin = "";
for (var idx in casts) {
castsjoin = castsjoin + casts[idx].name + " / ";
}
return castsjoin.substring(0, castsjoin.length - 2);
}
function convertToCastInfos(casts) {
var castsArray = []
for (var idx in casts) {
var cast = {
img: casts[idx].avatars ? casts[idx].avatars.large : "",
name: casts[idx].name
}
castsArray.push(cast);
}
return castsArray;
}
export {
convertToCastString,
convertToCastInfos
}
// const formatTime = date => {
// const year = date.getFullYear()
// const month = date.getMonth() + 1
// const day = date.getDate()
// const hour = date.getHours()
// const minute = date.getMinutes()
// const second = date.getSeconds()
// return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
// }
// const formatNumber = n => {
// n = n.toString()
// return n[1] ? n : '0' + n
// }
// module.exports = {
// formatTime: formatTime
// }