微信小程序入门与实战(11)——搜索页面、更多页面、电影详情页面

功能

搜索页面:实现点击搜索框,弹出搜索的电影结果
更多页面:点击电影页面的更多按钮,显示对应模块的更多电影
电影详情页面:点击对应的电影,进入对应的电影详情页面

搜索页面

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
// }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值