第五个页面:更多电影页面

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第五个页面:更多电影页面相关的知识,希望对你有一定的参考价值。

笔记内容:第五个页面:更多电影页面
笔记日期:2018-01-27


跳转到更多电影页面以及获取电影类型

因为要编写一个新的页面,所以第一件事情就是创建好目录以及文件:
技术分享图片

我们需要实现两个功能,一是点击电影资讯页面上的 “更多” 时,跳转到更多电影页面中,二是跳转时要获取相应的电影类型。

编辑movie-list-template.wxml,修改内容如下:

<import src=‘../movie/movie-template.wxml‘ />

<template name=‘movieListTemplate‘>
  <view class=‘movie-list-container‘ style=‘margin: 0;‘>
    <view class=‘inner-container‘ style=‘margin: 0;‘>
      <view class=‘movie-head‘>
        <text class=‘slogan‘>{{categoryTitle}}</text>
        <!-- 添加点击事件,并且把电影类型存储在自定义属性里 -->
        <view catchtap=‘onMoreTap‘ class=‘more‘ data-category="{{categoryTitle}}">
          <text class=‘more-text‘>更多</text>
          <image class=‘more-img‘ src=‘/images/icon/arrow-right.png‘></image>
        </view>
      </view>
      <view class=‘movies-container‘>
        <block wx:for=‘{{movies}}‘ wx:for-item=‘movie‘>
          <template is=‘movieTemplate‘ data=‘{{...movie}}‘ />
        </block> 
      </view>
    </view>
  </view>
</template>

在movie.js文件中增加一个事件方法,内容如下:

  // 跳转到更多电影页面
  onMoreTap: function (event) {
    // 获得电影类型
    var category = event.currentTarget.dataset.category;
    wx.navigateTo({
      // 通过参数把电影类型传递过去
      url: ‘more-movie/more-movie?category=‘ + category,
    });
  },

最后是在more-movie.js中测试一下是否能成功获取相应的电影类型:

Page({

  onLoad: function (options) {
    // 接收传递过来的参数
    var category = options.category;
    console.log(category);
  },

})

分别点击不同的电影类型上的 “更多“ ,看看控制台的输出是否对得上:
技术分享图片


动态设置导航栏标题

以上我们完成了电影类型的获得,在这之后就需要动态的把获得的数据设置为导航栏标题,这样点击不同的电影类型时就能在更多电影页面的导航栏上显示不同的标题。

官方给出的设置导航栏文档地址如下:

https://mp.weixin.qq.com/debug/wxadoc/dev/api/ui.html#wxsettopbartextobject

编辑more-movie.js文件内容如下:

Page({

  onLoad: function (options) {
    // 接收传递过来的参数
    var category = options.category;

    // 设置成变量才能在方法之间使用
    this.setData({
      navigateTitle: category,
    });
  },

  onReady: function (event) {
    // 动态设置导航栏标题
    wx.setNavigationBarTitle({
      title: this.data.navigateTitle,
    })
  }

})

以上新增的代码就简单的实现了动态设置导航栏标题。


在更多电影页面上加载数据

这一步我们需要实现在更多电影页面上,根据电影类型来向服务器加载不同电影类型的数据,由于这个请求API数据的方法挺通用的,所以我把它放到了util.js下,到时候就可以全局调用了,提高代码的复用性。

编辑util.js代码如下:

// 请求API的数据
function http (url, callBack) {

  // 通过reques来发送请求
  wx.request({
    url: url,
    method: ‘GET‘,
    header: {
      "Content-Type": "application/json"
    },
    success: function (res) {
      callBack(res.data);
    },
    fail: function (error) {
      console.log("API请求失败!请检查网络!" + error);
    }
  });
}

module.exports={
  convertToStarsArray: convertToStarsArray,
  http: http
}

编辑more-movie.js代码如下:

var app = getApp();
var util = require(‘../../../utils/util.js‘);

Page({
  data:{
    movies:{}
  },
  onLoad: function (options) {
    // 接收传递过来的参数
    var category = options.category;

    // 设置成变量才能在方法之间使用
    this.setData({
      navigateTitle: category,
    });

    var dataUrl = "";
    switch (category) {
      case "正在热映":
        dataUrl = app.globalData.doubanBase + ‘/v2/movie/in_theaters‘;
        break;
      case "即将上映":
        dataUrl = app.globalData.doubanBase + ‘/v2/movie/coming_soon‘;
        break;
      case "豆瓣电影Top250":
        dataUrl = app.globalData.doubanBase + ‘/v2/movie/top250‘;
        break;
    }
    util.http(dataUrl, this.processDoubanData)
  },

  // 处理API返回的数据,并绑定到数据集里
  processDoubanData: function (moviesDouban) {
    console.log(moviesDouban)
    // 存储处理完的数据
    var movies = [];
    for (var idx in moviesDouban.subjects) {
      var subject = moviesDouban.subjects[idx];
      var title = subject.title;
      // 处理标题过长
      if (title.length >= 6) {
        title = title.substring(0, 6) + "...";
      }

      var temp = {
        stars: util.convertToStarsArray(subject.rating.stars),
        title: title,
        average: subject.rating.average,
        coverageUrl: subject.images.large,
        movieId: subject.id
      };
      movies.push(temp);
    }

    this.setData({
      movies: movies
    });
  },

  onReady: function (event) {
    // 动态设置导航栏标题
    wx.setNavigationBarTitle({
      title: this.data.navigateTitle,
    })
  }

})

实现movie-grid template

以上我们已经完成了数据的处理,现在只需要完成页面代码即可因为这个更多电影页面的结构以及样式都需要进行复用,所以我们还是使用template把这些代码作为模板代码。

创建模板文件:
技术分享图片

movie-grid-template.wxml文件内容:

<import src="../movie/movie-template.wxml" />

<template name="movieGridTemplate">
  <view class=‘grid-container‘>
    <block wx:for="{{movies}}" wx:for-item="movie">
      <view class=‘single-view-container‘>
        <template is="movieTemplate" data="{{...movie}}" />
      </view>
    </block>
  </view>
</template>

movie-grid-template.wxss文件内容:

@import "../movie/movie-template.wxss";

.single-view-container{
  float: left; 
  margin-bottom: 40rpx;
}

.grid-container{
  margin: 40rpx 0 40rpx 6rpx;
}

more-movie.wxml就只需要引用模板即可,代码的可复用性越高,需要写的代码就越少:

<import src="../movie-grid/movie-grid-template.wxml" />
<template is="movieGridTemplate" data="{{movies}}" />

more-movie.wxss也是只需要引用模板即可:

@import "../movie-grid/movie-grid-template.wxss";

运行效果:
技术分享图片


实现上滑加载更多数据

以上我们实现了更多电影页面,但是每次只能加载20条电影数据,我们希望能够有一个上滑加载更多数据的功能,所以本节就是演示如何实现这样一个功能。

实现这样一个功能我们需要使用到scroll-view组件,该组件的官方说明文档地址如下:

https://mp.weixin.qq.com/debug/wxadoc/dev/component/scroll-view.html

编辑movie-grid-template.wxml文件内容,将view换成scroll-view:

<import src="../movie/movie-template.wxml" />

<template name="movieGridTemplate">
  <scroll-view scroll-y="true" scroll-x="false" bindscrolltolower="onScrollLower" class=‘grid-container‘>
    <block wx:for="{{movies}}" wx:for-item="movie">
      <view class=‘single-view-container‘>
        <template is="movieTemplate" data="{{...movie}}" />
      </view>
    </block>
  </scroll-view>
</template>

编辑movie-grid-template.wxss文件内容,给grid-container设置一个固定的高度,因为需要有一个固定的高度才知道是否已经滚动到底部了:

@import "../movie/movie-template.wxss";

.single-view-container{
  float: left; 
  margin-bottom: 40rpx;
}

.grid-container{
  /*必须要给一个固定的高度*/
  height: 1300rpx;
  margin: 40rpx 0 40rpx 6rpx;
}

最后是编辑more-movie.js文件,这一步我们需要完成三件事情:

1.实现事件方法,当触发bindscrolltolower时向API请求更多的数据

2.我们都知道第一次请求API时默认是请求0-19条数据,所以我们需要有一个变量充当计数器,让这个变量的值在每一次请求成功后都进行累加,这样才能让start参数的值进行一个递增,例如第一次是0-19,第二次就得是20-39,第三次就是40-59......以此类推

3.能够实现不断的往后加载数据之后,我们需要将这些数据都整合起来,不然的话数据会进行覆盖,那么每一次加载都只能显示20条数据,这显然不是我们想要的效果。我们想要的是数据进行叠加,第一次显示20条数据,第二次显示40条数据,第三次显示60条数据......以此类推

理清思路后,编辑more-movie.js文件内容如下:

var app = getApp();
var util = require(‘../../../utils/util.js‘);

Page({
  data: {
    movies: {},
    totalCount: 0,
    isEmpty:true,  // 用于判断movies是否为空,是的话就是第一次请求数据
  },
  onLoad: function (options) {
    // 接收传递过来的参数
    var category = options.category;

    // 设置成变量才能在方法之间使用
    this.setData({
      navigateTitle: category,
    });

    var dataUrl = "";
    switch (category) {
      case "正在热映":
        dataUrl = app.globalData.doubanBase + ‘/v2/movie/in_theaters‘;
        break;
      case "即将上映":
        dataUrl = app.globalData.doubanBase + ‘/v2/movie/coming_soon‘;
        break;
      case "豆瓣电影Top250":
        dataUrl = app.globalData.doubanBase + ‘/v2/movie/top250‘;
        break;
    }
    this.setData({
      requestUrl: dataUrl
    });
    util.http(dataUrl, this.processDoubanData)
  },

  // 触发bindscrolltolower事件时加载更多数据
  onScrollLower: function (event) {
    var nextUrl = this.data.requestUrl + "?start=" + this.data.totalCount + "&count=20";
    util.http(nextUrl, this.processDoubanData)
  },

  // 处理API返回的数据,并绑定到数据集里
  processDoubanData: function (moviesDouban) {
    console.log(moviesDouban)
    // 存储处理完的数据
    var movies = [];
    for (var idx in moviesDouban.subjects) {
      var subject = moviesDouban.subjects[idx];
      var title = subject.title;
      // 处理标题过长
      if (title.length >= 6) {
        title = title.substring(0, 6) + "...";
      }

      var temp = {
        stars: util.convertToStarsArray(subject.rating.stars),
        title: title,
        average: subject.rating.average,
        coverageUrl: subject.images.large,
        movieId: subject.id
      };
      movies.push(temp);
    }
    // 将新旧数据进行整合在一起
    var totalMovies={};
    if(!this.data.isEmpty){
      // 不为空代表不是第一次请求才进行整合
      totalMovies=this.data.movies.concat(movies);
    }else{
      // 第一次请求则需要不需要整合,并且需要改变isEmpty的状态
      totalMovies = movies;
      this.data.isEmpty=false;
    }
    this.setData({
      movies: totalMovies
    });
    // 计数器,数据绑定成功后才进行累加
    this.data.totalCount += 20;
  },

  onReady: function (event) {
    // 动态设置导航栏标题
    wx.setNavigationBarTitle({
      title: this.data.navigateTitle,
    })
  }
})

设置loading状态

以上我们完成了更多数据的加载,但是只是这样的话,体验还不够良好,我们需要在数据加载时提示用户一个loading状态,这样体验起来就没那么生硬。

有几个API都可以实现这个loading的效果,我这里使用的是wx.showNavigationBarLoading(),以下是关于交互反馈API的官方文档地址:

https://mp.weixin.qq.com/debug/wxadoc/dev/api/ui.html#wxshownavigationbarloading

编辑more-movie.js文件中的onScrollLower以及processDoubanData方法,在方法代码的末尾加上以下内容:

onScrollLower: function (event) {
            // 其他代码忽略

    // 设置loading状态
    wx.showNavigationBarLoading();
},

processDoubanData: function (moviesDouban) {
            // 其他代码忽略

    // 结束loading状态
    wx.hideNavigationBarLoading();
},

通过这两个API就简单的实现了数据加载时提示loading状态。


实现下拉页面重新刷新数据

几乎所有的app里都有下拉页面重新刷新数据的功能,所以我们也希望有一个这样的功能。不过目前有一个小问题,我们是使用scroll-view组件来实现下滑加载更多数据的,但是130400版本更新后却导致下拉刷新和scroll-view不能同时使用。

导致onPullDownRefresh事件函数无法执行的原因是页面里包含一个scroll-view组件。而scroll-view组件和onPullDownRefresh在130400版本里是冲突的。当我们在页面里滑动scroll-view时,只是滑动这个组件,不再可以触发onPullDownRefresh。当然,你还是可以在scroll-view区域外滑动页面执行onPullDownRefresh。什么意思呢?看下面的图:
技术分享图片

点击箭头那块儿的空白部分依然可以执行onPullDownRefresh,但除此之外任何位置都不可以执行刷新事件。原因是因为,箭头的空白部分不属于scroll-view这个组件的区域,它是属于page页面的区域,page页面依然可以执行onPullDownRefresh。但如果是在scroll-view组件内部去拉动页面,则滑动的动作只对scroll-view组件有效,不再对page页面有效,自然就不会再触发页面的onPullDownRefresh。

解决方案如下(下拉刷新和加载更多同时存在的方法):

放弃使用scroll-view组件,改用view组件。那么既然放弃了scroll-view组件,上滑加载更多就不能再使用scroll-view的bindscrolltolower="onScrollLower"事件。

那么view组件如何监控上滑到底的事件?MINA在Page里还提供了一个onReachBottom事件,使用这个事件来监听页面上滑到底。

具体改动:

more-movie.js文件:

// 触发onReachBottom事件时加载更多的数据
  onReachBottom: function (event) {
    var nextUrl = this.data.requestUrl + "?start=" + this.data.totalCount + "&count=20";
    util.http(nextUrl, this.processDoubanData);

    // 设置loading状态
    wx.showNavigationBarLoading();
  },

将原本的onScrollLower方法更名成onReachBottom,方法的内容无需任何改动。

movie-grid-template.wxml文件:

<import src="../movie/movie-template.wxml" />

<template name="movieGridTemplate">
  <view class=‘grid-container‘>
    <block wx:for="{{movies}}" wx:for-item="movie">
      <view class=‘single-view-container‘>
        <template is="movieTemplate" data="{{...movie}}" />
      </view>
    </block>
  </view>
</template>

完成以上的修改后,才能开始着手开始实现我们的下拉页面重新刷新数据的功能,首先我们需要编辑more-movie.json文件,增加如下内容,以开启下拉刷新功能:

{
  "enablePullDownRefresh": "true"
}

该配置语句的官网说明文档地址:

https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html

当下拉页面下拉刷新时会触发onPullDownRefresh事件方法,所以最后就是编辑more-movie.js文件,实现onPullDownRefresh方法,以及在processDoubanData方法里需要添加一句代码:

  // 当下拉刷新时会触发onPullDownRefresh方法,所以我们要实现它
  onPullDownRefresh: function (event) {
    var refreshUrl = this.data.requestUrl + "?start=0&count=20";
    util.http(refreshUrl, this.processDoubanData);

    // 清空movies里的数据
    this.data.movies = {};
    // 将totalCount归零
    this.data.totalCount = 0;
    // 并且改变isEmpty状态
    this.data.isEmpty = true;

    // 设置loading状态
    wx.showNavigationBarLoading();
  },

  processDoubanData: function (moviesDouban) {
          // 其他代码忽略

    // 停止刷新数据
    wx.stopPullDownRefresh();
  },

关于backgroundColor 到底设置的是哪里的颜色

很多人以为 backgroundColor 设置的是页面的背景颜色,而且官方文档上写的也不是很清楚,就写了个 “窗口的背景色” 。经过试验发现实际上 backgroundColor 设置的是我们下拉页面时的那个背景颜色,我们可以做一个简单的小实验,在more-movie.json文件中增加一行配置:

{
  "enablePullDownRefresh": "true",
  "backgroundColor":"red"
}

然后到more-movie页面中,然后下拉页面,可以看到背景颜色是我们设置的red红色:
技术分享图片

或许不能说是下拉页面时的背景颜色,严格来说是Page页面底层下的背景颜色,也就是脱离了Page页面时裸露出来的页面背景。

以上是关于第五个页面:更多电影页面的主要内容,如果未能解决你的问题,请参考以下文章

解决方案电影标题中缺少代码的片段,完成挑战更多[关闭]

在 Rails 中通过 AJAX 加载更多用户电影

第五条知识点

豆瓣电影

上市电影+他们的海报

《神秘海域》电影第五次换导演!不过主角还是荷兰弟