29.实现下拉刷新,笔记日期

作者: 编程  发布:2019-11-29

29.实现下拉刷新

more-movie.json

{
  "enablePullDownRefresh": true
}

more-movie.js

onPullDownRefresh: function () {
    var refreshUrl = this.data.requsetUrl +
      "?star=0&count=20";
    this.data.movies = {};
    this.data.isEmpty = true;
    this.data.totalCount = 0;
    util.http(refreshUrl, this.processDoubanData);
    wx.showNavigationBarLoading();
  },

  processDoubanData:function(data){
    .
    .
    .
    this.data.totalCount += 20;
    wx.hideNavigationBarLoading()
    wx.stopPullDownRefresh()
  },

22.星星评分组件的实现

utils/util.js

function convertToStarArray(stars) {
  var num = stars.toString().substring(0, 1)
  var array = []
  for (var i = 1; i <= 5; i++) {
    if (i <= num) {
      array.push(1)
    } 
    else {
      array.push(0)
    }
  }
  return array;
}

module.exports = {
  convertToStarArray: convertToStarArray,
};

movies.js

var util = require('../../utils/util.js')

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

movie.wxml

<import src="../stars/stars-template.wxml" />
<template name="movieTemplate">
    <view class="movie-container">
      <image class="movie-img" src='{{coverageUrl}}'></image>
      <text class="movie-title">{{title}}</text>
      <template is="starsTemplate" data="{{stars:stars,score:average}}" />
    </view>
  </template>

stars-template.wxml

<template name="starsTemplate">
  <view class="stars-container">
    <view class='stars'>
      <block wx:for="{{stars}}" wx:for-item="i">
        <image wx:if="{{i}}" src='/images/icon/star.png'></image>
        <image wx:else src='/images/icon/none-star.png'></image>
      </block>
    </view>
    <text class="star-score ">{{average}}</text>
  </view>
</template>

9159.com 1

获取正在热映、即将上映以及Top250的数据

先把API地址存储到一个全局变量里,方便调用,之后就只需要加上url的后缀即可,编辑app.js内容如下:

App({

  globalData:{
    g_isPlayingMusic:false,
    g_currentMusicPostId:"",
    g_beforeMusicPostId: "",
    doubanBase:'https://api.douban.com'  # API地址
  },

});

我们还需要完善一下页面的样式,让每个模板之间都有一个就间隔,编辑movies.wxml内容如下:

<import src="movie-list/movie-list-template.wxml" />
<view class='container'>
  <view>
    <template is="movieListTemplate" />
  </view>
  <view>
    <template is="movieListTemplate" />
  </view>
  <view>
    <template is="movieListTemplate" />
  </view>
</view>

然后编辑movies.wxss内容如下:

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

.container{
  background-color: #f2f2f2;
}

.container view{
  margin-bottom: 30rpx;
}

最后编写获取数据的逻辑代码,将获取到的数据先在控制台输出,编辑movies.js内容如下:

var app = getApp();

Page({

  onLoad: function (event) {
    // start=0&count=3 表示只拿取三条数据
    var inTheatersUrl = app.globalData.doubanBase + '/v2/movie/in_theaters?start=0&count=3';
    var comingSoonUrl = app.globalData.doubanBase + '/v2/movie/coming_soon?start=0&count=3';
    var top250Url = app.globalData.doubanBase + '/v2/movie/top250?start=0&count=3';

    this.getMovieListData(inTheatersUrl);
    this.getMovieListData(comingSoonUrl);
    this.getMovieListData(top250Url);
  },

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

})

控制台输出结果如下:
9159.com 2

可以看到已经成功获取数据了,接下来就是把这些数据绑定到页面上即可。


31.电影详情页面

movie-template.wxml

<view class="movie-container" catchtap="onMovieTap" data-movieId="{{movieId}}">

movie.js

 onMovieTap:function(event) {
    var movieId = event.currentTarget.dataset.movieid;
    wx.navigateTo({
      url: "movie-detail/movie-detail?id=" + movieId
    })
  },

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

module.exports = {
  convertToStarArray: convertToStarArray,
  http: http,
  convertToCastString: convertToCastString,
  convertToCastInfos: convertToCastInfos
};

movie-detail.js

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

Page({
  data:{
    movie:{}
  },
  onLoad:function(options){
    var movieId = options.id;
    var url = app.globalData.g_baseUrl +
      "/v2/movie/subject/" + movieId;
    util.http(url,this.processDoubanData);
  },
  processDoubanData:function(data){
    var director = {
      avatar: "",
      name: "",
      id: ""
    }
    if (data.directors[0] != null) {
      if (data.directors[0].avatars != null) {
        director.avatar = data.directors[0].avatars.large

      }
      director.name = data.directors[0].name;
      director.id = data.directors[0].id;
    }
    var movie = {
      movieImg: data.images ? data.images.large : "",
      country: data.countries[0],
      title: data.title,
      originalTitle: data.original_title,
      wishCount: data.wish_count,
      commentCount: data.comments_count,
      year: data.year,
      generes: data.genres.join("、"),
      stars: util.convertToStarArray(data.rating.stars),
      score: data.rating.average,
      director: director,
      casts: util.convertToCastString(data.casts),
      castsInfo: util.convertToCastInfos(data.casts),
      summary: data.summary
    }
    console.log(movie)
    this.setData({
      movie:movie
    })
  }
})

movie-detail.wxml

<import src="../stars/stars-template.wxml" />
<view class="container">
  <image class="head-img" src="{{movie.movieImg}}" mode="aspectFill" />
  <view class="head-img-hover" data-src="{{movie.movieImg}}" catchtap="viewMoviePostImg">
    <text class="main-title">{{movie.title}}</text>
    <text class="sub-title">{{movie.country + " · "+movie.year}}</text>
    <view class="like">
      <text class="highlight-font">
        {{movie.wishCount}}
      </text>
      <text class="plain-font">
        人喜欢
      </text>
      <text class="highlight-font">
        {{movie.commentCount}}
      </text>
      <text class="plain-font">
        条评论
      </text>
    </view>
  </view>
  <image class="movie-img" src="{{movie.movieImg}}" data-src="{{movie.movieImg}}" catchtap="viewMoviePostImg"/>
  <view class="summary">
    <view class="original-title">
      <text>{{movie.originalTitle}}</text>
    </view>
    <view class="flex-row">
      <text class="mark">评分</text>
      <template is="starsTemplate" data="{{stars:movie.stars, score:movie.score}}" />
    </view>
    <view class="flex-row">
      <text class="mark">导演</text>
      <text>{{movie.director.name}}</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.generes}}</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="cast">
    <text class="cast-font"> 影人</text>
    <scroll-view class="cast-imgs" scroll-x="true" style="width:100%">
      <block wx:for="{{movie.castsInfo}}" wx:for-item="item">
        <view class="cast-container">
          <image class="cast-img" src="{{item.img}}"></image>
          <text class="cast-name">{{item.name}}</text>
        </view>
      </block>
    </scroll-view>
  </view>
</view>

movie-detail.wxss

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

.container{
    display:flex;
    flex-direction: column;
}

.head-img{
    width:100%;
    height: 320rpx;
}

.head-img-hover{
    width: 100%;
    height: 320rpx;
    position:absolute;
    top:0;
    left:0;
    display:flex;
    flex-direction: column;
}

.main-title{
    font-size: 19px;
    color:#fff;
    font-weight:bold;
    margin-top: 50rpx;
    margin-left: 40rpx;
    letter-spacing: 2px;
}

.sub-title{
    font-size: 28rpx;
    color:#fff;
    margin-left: 40rpx;
    margin-top: 30rpx;
}

.like{
    display:flex;
    flex-direction: row;
    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;
    color: #777777;
}

.original-title{
    color: #1f3463;
    font-size: 24rpx;
    font-weight: bold;
    margin-bottom: 40rpx;
}

.flex-row{
    display:flex;
    flex-direction: row;
    margin-bottom: 10rpx;
}

.mark{
    margin-right: 30rpx;
    white-space:nowrap;
    color: #999999;
}

.hr{
    margin-top:45rpx;
    height:1px;
    width: 100%;
    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;
}

.cast{
    margin-left:40rpx;
    display:flex;
    flex-direction: column;
    margin-top:50rpx;
}

.cast-font{
    color: #999;
    margin-bottom: 40rpx;
}

.cast-container{
    display:inline-flex;
    flex-direction: column;
    margin-bottom: 50rpx;
    margin-right: 40rpx;
    width: 170rpx;
    text-align:center;
    white-space: normal;
}

.cast-imgs{
    white-space: nowrap;
}

.cast-img{
    width: 170rpx;
    height: 210rpx;
}
.cast-name{
    margin: 10rpx auto 0;
}

结果

9159.com 3

30.电影搜索功能实现

movies.wxml

<import src="movie-list/movie-list-template.wxml" />
<import src="movie-grid/movie-grid-template.wxml" />
<view class="search">
  <icon type="search" class="search-img" size="13" color="#405f80"></icon>
  <input type="text" placeholder="西虹市首富" placeholder-class="placeholder" bindfocus="onBindFocus" bindconfirm="onBindBlur"/>
   <image wx:if="{{searchPanelShow}}" src="/images/icon/xx.png" class="xx-img" bindtap="onCancelImgTap"></image> 
</view>
.
.

<view class="search-panel" wx:if="{{searchPanelShow}}">
    <template is="movieGridTemplate" data="{{...searchResult}}"/>
</view>

movies.wxss

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

.search {
  background-color: #f2f2f2;
  height: 80rpx;
  width: 100%;
  display: flex;
  flex-direction: row;
}

.search-img {
  margin: auto 0 auto 20rpx;
}

.search input {
  height: 100%;
  width: 600rpx;
  margin-left: 20px;
  font-size: 28rpx;
}

.placeholder {
  font-size: 14px;
  color: #d1d1d1;
  margin-left: 20rpx;
}

.search-panel{
    position:absolute;
    top:80rpx;
}

.xx-img{
    height: 30rpx;
    width: 30rpx;
    margin:auto 0 auto 10rpx;
}

movies.js

Page({
  data: {
    inTheaters: {},
    comingSoon: {},
    top250: {},
    searchResult: {},
    containerShow: true,
    searchPanelShow: false
  },

    onBindFocus: function (event) {
    this.setData({
      containerShow: false,
      searchPanelShow: true
    })
  },
  onCancelImgTap: function (event) {
    this.setData({
      containerShow: true,
      searchPanelShow: false,
      searchResult: {}
    })
  },

  onBindBlur: function (event) {
    var text = event.detail.value
    var searchUrl = app.globalData.g_baseUrl + "/v2/movie/search?q=" + text;
    this.getMovieList(searchUrl, "searchResult", "");
  },

结果

9159.com 4

21.电影页面数据绑定

movies.js

var app = getApp();
Page({
  data: {
    inTheaters: {},
    comingSoon: {},
    top250: {},
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    var baseUrl = app.globalData.g_baseUrl;
    var inTheatersUrl = baseUrl +"/v2/movie/in_theaters" + "?start=0&count=3";
    var comingSoonUrl = baseUrl + "/v2/movie/coming_soon" + "?start=0&count=3";
    var top250Url = baseUrl + "/v2/movie/top250" + "?start=0&count=3";
    this.getMovieList(inTheatersUrl, "inTheaters")
    this.getMovieList(comingSoonUrl, "comingSoon");
    this.getMovieList(top250Url, "top250");
  },

  getMovieList(url, setKey) {
    var that = this
    wx.request({
      url: url,
      data: {},
      method: 'GET',
      header: {
        'content-type': 'json' // 默认值 application/json
      },
      success: function (res) {
        console.log(res)
        that.processDoubanDate(res.data, setKey)
      }
    })
  },

  processDoubanDate: function (moviesDouban, setKey) {
    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 = {
        title: title,
        average: subject.rating.average,
        coverageUrl: subject.images.large,
        movieId: subject.id
      }
      movies.push(temp)
    }
    var readyData = {};
    readyData[setKey] = {
      movies: movies
    }
    this.setData(readyData);

  }
})

movies.wxml

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

<view class="container">
  <view class="movies-template">
    <template is="movielistTemplate" data="{{...inTheaters}}" />
  </view>
  <view class="movies-template">
    <template is="movielistTemplate" data="{{...comingSoon}}" />
  </view>
  <view class="movies-template">
    <template is="movielistTemplate" data="{{...top250}}" />
  </view>
</view>

movie-list-template.wxml

<import src="../movie/movie-template.wxml" />
<template name="movielistTemplate">
  <view class="movie-lsit-container">
    <view class="inner-container">
      <view class="movie-head">
        <text class="slogan">正在热映</text>
        <view class="more">
          <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-template.wxml

<import src="../stars/stars-template.wxml" />
<template name="movieTemplate">
    <view class="movie-container">
      <image class="movie-img" src='{{coverageUrl}}'></image>
      <text class="movie-title">{{title}}</text>
      <template is="starsTemplate" data="{{average}}" />
    </view>
  </template>

预览

9159.com 5

加入tab选项卡

现在我们就可以开始编写电影资讯页面了,为此我们需要给我们的小程序加入一个tab选项卡,这样才能够方便的切换到不同的主题页面上。像这个tab选项卡这种常用的组件,微信已经提供了现成的,无需我们自己去实现。

如果小程序是一个多 tab 应用(客户端窗口的底部或顶部有 tab 栏可以切换页面),可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面。

官方的说明文档如下:

注:tabBar 中的 list 属性是一个数组,只能配置最少2个、最多5个 tab,tab 按数组的顺序排序。

首先我们需要构建电影资讯页面的目录、文件,在pages目录下创建movies目录并在该目录下创建相应的文件:
9159.com 6

9159.com,在app.json里配置movies页面以及tabBar:

{
  "pages": [
    "pages/welcome/welcome",
    "pages/posts/post",
    "pages/posts/post-detail/post-detail",
    "pages/movies/movies"  // 配置movies页面
  ],
  "window": {
    "navigationBarBackgroundColor": "#405f80"
  },
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/posts/post",  // 跳转的页面
        "text": "阅读"  // 选项卡的文本内容
      },
      {
        "pagePath": "pages/movies/movies",
        "text": "电影"
      }
    ]
  }
}

配置完app.json后还需要修改welcome.js代码中的跳转方法,需要将原本的redirectTo方法修改成switchTab方法来实现页面的跳转。switchTab方法用于跳转到有 tabBar 选项卡的页面,并关闭其他所有非 tabBar 页面。修改代码如下:

Page({
  onTap:function(){
    wx.switchTab({
      url: "../posts/post",
    });
  },
})

官方文档如下:

完成以上修改后,编译运行效果如下:
9159.com 7

注:选项卡的顺序是与list里的元素顺序一致的。


28.设置loading状态

more-movie.js

onScrollLower: function (event) {
    var nextUrl = this.data.requsetUrl +
      "?start=" + this.data.totalCount + "&count=20";
    util.http(nextUrl, this.processDoubanData);
    wx.showNavigationBarLoading()
  },

  processDoubanData:function(data){
    .
    .

    this.setData({
      movies: totalMovies
    })
    this.data.totalCount += 20;
    wx.hideNavigationBarLoading()
  },

23.更换电影分类标题

movies.js

this.getMovieList(inTheatersUrl, "inTheaters", "正在热映")
this.getMovieList(comingSoonUrl, "comingSoon", "即将上映");
this.getMovieList(top250Url, "top250", "豆瓣Top250");

 getMovieList(url, setKey, categoryTitle) {
    .
    .
    .
      success: function (res) {
        console.log(res)
        that.processDoubanDate(res.data, setKey,categoryTitle)
      }
    })
  },

processDoubanDate: function (moviesDouban, setKey,categoryTitle) {
    .
    .
    .

    readyData[setKey] = {
      movies: movies,
      categoryTitle: categoryTitle
    }
    this.setData(readyData);

  }

movie-list-template.wxml

<text class="slogan">{{categoryTitle}}</text>

9159.com 8

点击轮播图跳转到文章详情页面

之前的文章列表页面还有一个小功能没有实现,就是点击点击轮播图就能跳转到相应的文章详情页面,这个和点击文章列表跳转到文章详情页面的实现方式是一样的。

post.wxml修改轮播图代码如下:

<!-- 添加点击事件,这里利用了事件冒泡的机制 -->
<swiper catchtap='onSwiperTap' indicator-dots='true' autoplay='true' interval='5000'>
    <!-- 每一项里都放了一个图片 -->
    <swiper-item>
      <!-- data-postId对应的是需要跳转的文章id -->
      <image src='wx.png' data-postId="3"></image>
    </swiper-item>
    <swiper-item>
      <image src='vr.png' data-postId="4"></image>
    </swiper-item>
    <swiper-item>
      <image src='iqiyi.png' data-postId="5"></image>
    </swiper-item>
</swiper>

post.js文件增加如下代码:

  onSwiperTap:function(event){
    // target和currentTarget的区别在于,前者代表的是当前点击的组件,后者代表的是事件捕获的组件
    // 在这段代码里,target代表image组件,currentTarget代表swiper组件
    var postId = event.target.dataset.postid;
    wx.navigateTo({
      url: 'post-detail/post-detail?id=' + postId,
    });
  },

27.实现上滑加载更多数据

movie-grid-template.wxml

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

more-movie.js

var util = require('../../../utils/util.js')
var app = getApp();
Page({
  data:{
    categoryTitle: '',
    movies: {},
    requsetUrl: '',
    isEmpty: true,
    totalCount: 0
  },
  onLoad: function (options) {
    .
    .
    .
    this.data.requsetUrl = dataUrl;
    util.http(dataUrl, this.processDoubanData)
  },

  processDoubanData:function(data){
   .
   .
   .

    var totalMovies = {}
    if (!this.data.isEmpty) {
      totalMovies = this.data.movies.concat(movies)
    } else {
      totalMovies = movies
      this.data.isEmpty = false
    }
    this.setData({
      movies: totalMovies
    })
    this.data.totalCount += 20;
  },

  onScrollLower:function(event){
    var nextUrl = this.data.requsetUrl + 
    "?start=" + this.data.totalCount + "&count=20";
    util.http(nextUrl,this.processDoubanData)
  },

电影页面嵌套template分析

我们需要做一个这样的电影资讯页面:
9159.com 9

根据分析效果图,可以看到页面的布局是一排一排重复的的,每一排里都有三个电影,所以这样的重复性的布局以及样式我们可以做成一个template进行复用:
9159.com 10

当点击 “更多” 时进入的页面效果图如下:
9159.com 11

从效果图,可以看到图片、电影名称以及评分都是和电影资讯页面上的布局以及样式是重复的,所以我们还需要把这部分做成第二个template进行复用:
9159.com 12

再来看一张效果图:
9159.com 13

这是电影的详情页面,这里也用到了一个评分样式,这个样式也是重复的,所以我们还需要把这个样式做成第三个template进行复用。


星星评分组件的实现

接着就是将星星评分的组件完成,我的思路是使用将表示星星数据处理成0和1来表示两种星星图片,而这个0和1存储在一个数组里,到时候就根据数组里的元素来决定显示哪一个星星图片。由于这个数据的处理是通用的,之后可能需要在别的地方调用它,所以我们先在根下新建一个目录,并在目录中创建一个.js文件,将代码写在这个文件里:

9159.com 14

util.js内容如下:

// 生成一个用来表示星星数量的数组
function convertToStarsArray(stars) {
  var num = stars.toString().substring(0, 1);
  var array = [];
  for (var i = 1; i <= 5; i++) {
    if (i <= num) {
      array.push(1);
    } else {
      array.push(0);
    }
  }
  return array;
}

module.exports={
  convertToStarsArray: convertToStarsArray
}

然后在movies.js里导入这个模块,并调用该方法:

var app = getApp();
// 导入模块
var util = require('../../utils/util.js');

Page({
  data: {
    // 需要有一个初始值
    inTheaters: {},
    comingSoon: {},
    top250: {}
  },
  onLoad: function (event) {
    var inTheatersUrl = app.globalData.doubanBase + '/v2/movie/in_theaters?start=0&count=3';
    var comingSoonUrl = app.globalData.doubanBase + '/v2/movie/coming_soon?start=0&count=3';
    var top250Url = app.globalData.doubanBase + '/v2/movie/top250?start=0&count=3';

    this.getMovieListData(inTheatersUrl, "inTheaters");
    this.getMovieListData(comingSoonUrl, "comingSoon");
    this.getMovieListData(top250Url, "top250");
  },

  // 请求API的数据
  getMovieListData: function (url, settedkey) {
    var that = this;
    // 通过reques来发送请求
    wx.request({
      url: url,
      method: 'GET',
      header: {
        "Content-Type": "application/json"
      },
      success: function (res) {
        that.processDoubanData(res.data, settedkey);
      },
      fail: function () {
        console.log("API请求失败!请检查网络!")
      }
    });
  },

  // 处理API返回的数据
  processDoubanData: function (moviesDouban, settedkey) {
    // 存储处理完的数据
    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 readyData = {};
    readyData[settedkey] = {
      movies: movies
    };
    this.setData(readyData);
  },

})

修改模板文件中的数据绑定语句,修改movie-template.wxml内容如下:

<import src='../stars/stars-template.wxml' />
<template name='movieTemplate'>
  <view class='movie-container'>
    <image class='movie-img' src='{{coverageUrl}}'></image>
    <text class='movie-title'>{{title}}</text>
    <!-- 这种数据绑定的方式是重新生成两个数据,相当于将它们重命名了,只有这样才能够传递两个参数 -->
    <template is='starsTemplate' data="{{stars:stars, score: average}}" />
  </view>
</template>

最后是stars-template.wxml:

<template name='starsTemplate'>
  <view class='stars-container'>
    <view class='stars'>
      <!-- 遍历数组元素 -->
      <block wx:for="{{stars}}" wx:for-item="i">
        <!-- 元素不为0则显示亮着的星星图片 -->
        <image wx:if="{{i}}" src='icon/star.png'></image>
        <!-- 元素为0则显示灰色的星星图片 -->
        <image wx:else src='icon/none-star.png'></image>
      </block>
    </view>
    <text class='star-score'>{{score}}</text>
  </view>
</template>

电影页面数据绑定

编辑movies.js内容如下:

var app = getApp();

Page({
  data: {
    // 需要有一个初始值
    inTheaters: {},
    comingSoon: {},
    top250: {}
  },
  onLoad: function (event) {
    var inTheatersUrl = app.globalData.doubanBase + '/v2/movie/in_theaters?start=0&count=3';
    var comingSoonUrl = app.globalData.doubanBase + '/v2/movie/coming_soon?start=0&count=3';
    var top250Url = app.globalData.doubanBase + '/v2/movie/top250?start=0&count=3';

    this.getMovieListData(inTheatersUrl, "inTheaters");
    this.getMovieListData(comingSoonUrl, "comingSoon");
    this.getMovieListData(top250Url, "top250");
  },

  // 请求API的数据
  getMovieListData: function (url, settedkey) {
    var that = this;
    // 通过reques来发送请求
    wx.request({
      url: url,
      method: 'GET',
      header: {
        "Content-Type": "application/json"
      },
      success: function (res) {
        that.processDoubanData(res.data, settedkey);
      },
      fail: function () {
        console.log("API请求失败!请检查网络!")
      }
    });
  },

  // 处理API返回的数据
  processDoubanData: function (moviesDouban, settedkey) {
    // 存储处理完的数据
    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 = {
        title: title,
        average: subject.rating.average,
        coverageUrl: subject.images.large,
        movieId: subject.id
      };
      movies.push(temp);
    }

    // 动态赋值
    var readyData = {};
    readyData[settedkey] = {
      movies: movies
    };
    this.setData(readyData);
  },

})

编辑movies.wxml内容如下:

<import src="movie-list/movie-list-template.wxml" />
<view class='container'>
  <view>
    <template is="movieListTemplate" data='{{...inTheaters}}' />
  </view>
  <view>
    <template is="movieListTemplate" data='{{...comingSoon}}' />
  </view>
  <view>
    <template is="movieListTemplate" data='{{...top250}}' />
  </view>
</view>

然后就是将模板文件里的数据改为数据绑定形式的,movie-list-template.wxml:

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

<template name='movieListTemplate'>
  <view class='movie-list-container'>
    <view class='inner-container'>
      <view class='movie-head'>
        <text class='slogan'>正在热映</text>
        <view class='more'>
          <text class='more-text'>更多</text>
          <image class='more-img' src='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-template.wxml:

<import src='../stars/stars-template.wxml' />
<template name='movieTemplate'>
  <view class='movie-container'>
    <image class='movie-img' src='{{coverageUrl}}'></image>
    <text class='movie-title'>{{title}}</text>
    <template is='starsTemplate' data="{{average}}" />
  </view>
</template>

stars-template.wxml:

<template name='starsTemplate'>
  <view class='stars-container'>
    <view class='stars'>
      <image src='icon/star.png'></image>
      <image src='icon/star.png'></image>
      <image src='icon/star.png'></image>
      <image src='icon/star.png'></image>
      <image src='icon/star.png'></image>
    </view>
    <text class='star-score'>{{average}}</text>
  </view>
</template>

运行效果:
9159.com 15


完善tab选项卡

虽然我们已经完成了简单的选项卡效果,可是默认的样式实在不忍直视,所以我们还得完善这个tab选项卡。其实也很简单,加上两张图片就好了:

"tabBar": {
    "borderStyle":"white",
    "list": [
      {
        "pagePath": "pages/posts/post",
        "text": "阅读",
        "iconPath":"tab/yuedu.png",  // 没被选中时显示的图片
        "selectedIconPath":"tab/yuedu_hl.png"  // 被选中时显示的图片
      },
      {
        "pagePath": "pages/movies/movies",
        "text": "电影",
        "iconPath": "tab/dianying.png",
        "selectedIconPath": "tab/dianying_hl.png"
      }
    ]
  }

完成效果:
9159.com 16
9159.com 17

tabBar里还有一个position属性,该属性可以设置选项卡居顶部或居底部,例如我要选项卡居顶部,就可以在app.json文件中加上这一句配置:

"position":"top",

完成效果:
9159.com 18
9159.com 19


RESTful API简介及目前调用豆瓣API的问题

RESTful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

可重新表达的状态迁移(REST,英文:Representational State Transfer)是Roy Thomas Fielding博士于2000年在他的博士论文中提出来的一种万维网软件架构风格,目的是便于不同软件/程序在网络(例如互联网)中互相传递信息。

目前在三种主流的Web服务实现方案中,因为REST模式与复杂的SOAP和XML-RPC相比更加简洁,越来越多的web服务开始采用REST风格设计和实现。

需要注意的是,具象状态传输是设计风格而不是标准。REST通常基于使用HTTP,URI,和XML以及HTML这些现有的广泛流行的协议和标准。

  • 资源是由URI来指定。
  • 对资源的操作包括获取、创建、修改和删除资源,这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法。
  • 通过操作资源的表现形式来操作资源。
  • 资源的表现形式则是XML或者HTML,取决于读者是机器还是人,是消费web服务的客户软件还是web浏览器。当然也可以是任何其他的格式。

所以RESTful API就像是一个URL,只不过返回的数据不一定是HTML而已,一般都是用于返回JSON数据。

这一节我们需要调用豆瓣API来填充我们小程序的页面,豆瓣API文档地址如下:

微信小程序关于网络请求的API文档地址:

但是要注意:由于不明原因,现在豆瓣的API已经屏蔽微信小程序的调用请求了,我这里都是使用自己的服务器代理来实现调用的。

因为我个人的服务器地址不便于透露,所以我这里的示例代码依旧是使用豆瓣的地址,毕竟说不定哪天就不屏蔽了呢233。


3个嵌套template标签的实现

先创建好各个template的目录结构:
9159.com 20

我这里是先实现评分样式的template:

stars-template.wxml内容如下:

<template name='starsTemplate'>
  <view class='stars-container'>
    <view class='stars'>
      <image src='icon/star.png'></image>
      <image src='icon/star.png'></image>
      <image src='icon/star.png'></image>
      <image src='icon/star.png'></image>
      <image src='icon/star.png'></image>
    </view>
    <text class='star-score'>8.9</text>
  </view>
</template>

stars-template.wxss内容如下:

.stars-container{
  display: flex;
  flex-direction: row;
}

.stars{
  display: flex;
  flex-direction: row;
  height: 17rpx;
  margin-right: 24rpx;
  margin-top: 6rpx;
}

.stars image{
  padding-left: 3rpx;
  height: 17rpx;
  width: 17rpx;
}

.star-score{
  color: #1f3463
}

然后就是电影列表的template了,movie-template.wxml内容如下:

<import src='../stars/stars-template.wxml' />
<template name='movieTemplate'>
  <view class='movie-container'>
    <image class='movie-img' src='yourname.jpg'></image>
    <text class='movie-title'>你的名字.</text>
    <template is='starsTemplate' />
  </view>
</template>

movie-template.wxss内容如下:

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

.movie-container{
  display: flex;
  flex-direction: column;
  padding: 0 22rpx;
}

.movie-img{
  width: 200rpx;
  height: 270rpx;
  padding-bottom: 20rpx;
}

.movie-title{
  margin-bottom: 16rpx;
  font-size: 24rpx;
}

接着就是完成movie-list的template,movie-list-template.wxml内容如下:

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

<template name='movieListTemplate'>
  <view class='movie-list-container'>
    <view class='inner-container'>
      <view class='movie-head'>
        <text class='slogan'>正在热映</text>
        <view class='more'>
          <text class='more-text'>更多</text>
          <image class='more-img' src='icon/arrow-right.png'></image>
        </view>
      </view>
      <view class='movies-container'>
        <template is='movieTemplate' />
        <template is='movieTemplate' />
        <template is='movieTemplate' />
      </view>
    </view>
  </view>
</template>

movie-list-template.wxss内容如下:

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

.movie-list-container{
  background-color: #fff;
  display: flex;
  flex-direction: column;
}

.inner-container{
  margin: 0 auto 20rpx;
}

.movie-head{
  padding: 30rpx 20rpx 22rpx;
  /* 
  这种方式也能实现float: right;的效果
  display: flex;
  flex-direction: row;
  justify-content: space-between; 
  */
}

.slogan{
  font-size: 24rpx;
}

.more{
  float: right;
}

.more-text{
  vertical-align: middle;
  margin-right: 10rpx;
  color: #1f4ba5;
}

.more-img{
  width: 9rpx;
  height: 16rpx;
  vertical-align: middle;
}

.movies-container{
  display: flex;
  flex-direction: row;
}

运行效果:
9159.com 21


笔记内容:第四个页面:制作电影资讯页面
笔记日期:2018-01-18

更换电影分类标题

我们还有一个小细节没有完成,就是电影分类的标题还是硬编码的,所以需要改为数据绑定形式的,首先修改movies.js代码如下:

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

Page({
  data: {
    // 需要有一个初始值
    inTheaters: {},
    comingSoon: {},
    top250: {}
  },
  onLoad: function (event) {
    var inTheatersUrl = app.globalData.doubanBase + '/v2/movie/in_theaters?start=0&count=3';
    var comingSoonUrl = app.globalData.doubanBase + '/v2/movie/coming_soon?start=0&count=3';
    var top250Url = app.globalData.doubanBase + '/v2/movie/top250?start=0&count=3';

    this.getMovieListData(inTheatersUrl, "inTheaters", "正在热映");
    this.getMovieListData(comingSoonUrl, "comingSoon", "即将上映");
    this.getMovieListData(top250Url, "top250", "豆瓣电影Top250");
  },

  // 请求API的数据
  getMovieListData: function (url, settedkey, categoryTitle) {
    var that = this;
    // 通过reques来发送请求
    wx.request({
      url: url,
      method: 'GET',
      header: {
        "Content-Type": "application/json"
      },
      success: function (res) {
        that.processDoubanData(res.data, settedkey, categoryTitle);
      },
      fail: function () {
        console.log("API请求失败!请检查网络!")
      }
    });
  },

  // 处理API返回的数据
  processDoubanData: function (moviesDouban, settedkey, categoryTitle) {
    // 存储处理完的数据
    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 readyData = {};
    readyData[settedkey] = {
      categoryTitle: categoryTitle,
      movies: movies
    };
    this.setData(readyData);
  },

})

然后修改movie-list-template.wxml代码如下:

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

<template name='movieListTemplate'>
  <view class='movie-list-container'>
    <view class='inner-container'>
      <view class='movie-head'>
        <text class='slogan'>{{categoryTitle}}</text>
        <view class='more'>
          <text class='more-text'>更多</text>
          <image class='more-img' src='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>

完成效果:
9159.com 22

本文由9159.com发布于编程,转载请注明出处:29.实现下拉刷新,笔记日期

关键词: