当前位置:   article > 正文

微信小程序电影推荐demo实战开发小结(附源码及思维导图) ... ..._微信小程序微电影详情代码

微信小程序微电影详情代码

第一步 项目配置 一、编写app.json 对整个项目的公共配置 1、pages:配置页面路径(必须),列出所有的页面的路径,所有存在的页面都需要在此写出,否则在页面跳转的时候会报出找不到页面的错误2、window:窗口配置 ...

本文已获作者sesine授权转载,授权地址:http://www.jianshu.com/p/447b36463f09
更新日志

2016-11-30 更新内容:

  • 1.将网络请求从fetch改为官方的wx.request
  • 2.添加网络请求失败的提示
  • 3.将wxss中引入的网络图片路径改为base64的方式
  • 4.现已支持手机预览 : )
目录

[TOC]

github地址:https://github.com/yesifeng/wechat-weapp-movie

第一步 项目配置
一、编写app.json

对整个项目的公共配置

1、pages:配置页面路径(必须),列出所有的页面的路径,所有存在的页面都需要在此写出,否则在页面跳转的时候会报出找不到页面的错误
2、window:窗口配置,配置导航及窗口的背景色和文字颜色,还有导航文字和是否允许窗口进行下拉刷新
3、tabBar:tab栏配置,配置tab栏背景色及出现位置,上边框的颜色(目前只支持黑或白),文字颜色及文字选中颜色,最核心的配置是list即tab栏的列表,官方规定最少2个,最多5个,每个列表项目可配置页面路径、文字、图标及选中时图标的地址
4、network:网络配置,配置网络请求、上传下载文件、socket连接的超时时间
5、debug:调试模式,建议开发时开启(true),可以看到页面注册、页面跳转及数据初始化的信息,另外报错的错误信息也会比较详细

  1. {
  2. "pages": [
  3. "pages/popular/popular",
  4. "pages/coming/coming",
  5. "pages/top/top",
  6. "pages/search/search",
  7. "pages/filmDetail/filmDetail",
  8. "pages/personDetail/personDetail",
  9. "pages/searchResult/searchResult"
  10. ],
  11. "window": {
  12. "navigationBarBackgroundColor": "#47a86c",
  13. "navigationBarTextStyle": "white",
  14. "navigationBarTitleText": "电影推荐",
  15. "backgroundColor": "#fff",
  16. "backgroundTextStyle": "dark"
  17. },
  18. "tabBar": {
  19. "color": "#686868",
  20. "selectedColor": "#47a86c",
  21. "backgroundColor": "#ffffff",
  22. "borderStyle": "white",
  23. "list": [{
  24. "pagePath": "pages/popular/popular",
  25. "iconPath": "dist/images/popular_icon.png",
  26. "selectedIconPath": "dist/images/popular_active_icon.png",
  27. "text": "热映"
  28. }, {
  29. "pagePath": "pages/coming/coming",
  30. "iconPath": "dist/images/coming_icon.png",
  31. "selectedIconPath": "dist/images/coming_active_icon.png",
  32. "text": "待映"
  33. },{
  34. "pagePath": "pages/search/search",
  35. "iconPath": "dist/images/search_icon.png",
  36. "selectedIconPath": "dist/images/search_active_icon.png",
  37. "text": "搜索"
  38. },
  39. {
  40. "pagePath": "pages/top/top",
  41. "iconPath": "dist/images/top_icon.png",
  42. "selectedIconPath": "dist/images/top_active_icon.png",
  43. "text": "口碑"
  44. }]
  45. },
  46. "networkTimeout": {
  47. "request": 10000,
  48. "downloadFile": 10000
  49. },
  50. "debug": true
  51. }
二、确定目录结构

根据UI图,提取组件和公共样式/脚本,以及page的目录

  • comm - 公用的脚本及样式
    • script - 公共脚本
      • config.js 配置信息 (单页数据量,城市等)
      • fetch.js 接口调用 (电影列表及详情,人物详情、搜索)
    • style - 公共样式
      • animation.wxss 动画
  • component - 公用的组件
    • filmList - 电影列表
      • filmList.wxml - 组件结构
      • filmList.wxss - 组件样式
  • dist - 静态资源
    • images 本地图片,主要存导航的图标 (样式中不可引用本地图像资源)
  • pages - 页面
    • popular - 页面文件夹 ("popular"为自定义的页面名称,页面相关文件的文件名需与页面名相同)
      • popular.js 页面逻辑
      • popular.wxml 页面结构
      • popular.wxss 页面样式
      • popular.json 页面窗口配置 (可参考app.json中的window配置)
  • app.js - 小程序整体逻辑 (初始化、显示、隐藏的事件,以及存放全局数据)
  • app.json - 小程序公共配置
  • app.wxss - 小程序公共样式
第二步 编写组件  电影列表
结构
  1. <template name="filmList">
  2. <block wx:if="{{showLoading}}">
  3. <view class="loading">玩命加载中…</view>
  4. </block>
  5. <block wx:else>
  6. <scroll-view scroll-y="true" style="height: {{windowHeight}}rpx" bindscroll="scroll" bindscrolltolower="scrolltolower">
  7. <view class="film">
  8. <block wx:for="{{films}}" wx:for-index="filmIndex" wx:for-item="filmItem" wx:key="film">
  9. <view data-id="{{filmItem.id}}" class="film-item" catchtap="viewFilmDetail">
  10. <view class="film-cover">
  11. <image src="{{filmItem.images.large}}" class="film-cover-img"></image>
  12. <view class="film-rating">
  13. <block wx:if="{{filmItem.rating.average == 0}}">
  14. 暂无评分
  15. </block>
  16. <block wx:else>
  17. {{filmItem.rating.average}}分
  18. </block>
  19. </view>
  20. </view>
  21. <view class="file-intro">
  22. <view class="film-title">{{filmItem.title}}</view>
  23. <view class="film-tag">
  24. <view class="film-tag-item" wx:for="{{filmItem.genres}}" wx:for-item="filmTagItem" wx:key="filmTag" data-tag="{{filmTagItem}}" catchtap="viewFilmByTag">
  25. {{filmTagItem}}
  26. </view>
  27. </view>
  28. </view>
  29. </view>
  30. </block>
  31. <block wx:if="{{hasMore}}">
  32. <view class="loading-tip">拼命加载中…</view>
  33. </block>
  34. <block wx:else>
  35. <view class="loading-tip">没有更多内容了</view>
  36. </block>
  37. </view>
  38. </scroll-view>
  39. </block>
  40. </template>
样式
  1. import "../../comm/style/animation.wxss";
  2. .film {
  3. box-sizing: border-box;
  4. width: 750rpx;
  5. padding: 10rpx;
  6. display: flex;
  7. flex-wrap: wrap;
  8. flex-direction: row;
  9. justify-content: space-around;
  10. box-shadow: 0 0 40rpx #f4f4f4 inset;
  11. }
  12. .film-item {
  13. width: 350rpx;
  14. margin-bottom: 20rpx;
  15. border-radius: 10rpx;
  16. background-color: #fff;
  17. border: 1px solid #e4e4e4;
  18. box-shadow: 0 20rpx 40rpx #eee;
  19. overflow: hidden;
  20. animation: fadeIn 1s;
  21. }
  22. .film-cover, .film-cover-img {
  23. width: 350rpx;
  24. height: 508rpx;
  25. }
  26. .film-cover {
  27. position: relative;
  28. border-radius: 10rpx;
  29. overflow: hidden;
  30. }
  31. .film-rating {
  32. box-sizing: border-box;
  33. position: absolute;
  34. bottom: 0;
  35. left: 0;
  36. width: 100%;
  37. height: 50rpx;
  38. padding-right: 20rpx;
  39. font-size: 12px;
  40. text-align: right;
  41. line-height: 50rpx;
  42. background-color: rgba(0, 0, 0, .65);
  43. color: #fff;
  44. }
  45. .file-intro {
  46. padding: 16rpx;
  47. margin-top: -8rpx;
  48. }
  49. .film-title {
  50. white-space: nowrap;
  51. text-overflow: ellipsis;
  52. overflow: hidden;
  53. }
  54. .film-tag {
  55. width: 100%;
  56. margin-top: 10rpx;
  57. display: flex;
  58. justify-content: flex-start;
  59. }
  60. .film-tag-item {
  61. padding: 4rpx 6rpx;
  62. margin-right: 10rpx;
  63. font-size: 24rpx;
  64. box-shadow: 0 0 0 1px #ccc;
  65. border-top: 1px solid #fff;
  66. border-radius: 10rpx;
  67. background-color: #fafafa;
  68. color: #666;
  69. }
  70. .loading-tip {
  71. width: 100%;
  72. height: 80rpx;
  73. line-height: 80rpx;
  74. text-align: center;
  75. color: #ccc;
  76. }
使用方法

以popular(热映)页面为例

在popular.wxml中插入以下代码引入组件结构:

  1. <import src="../../component/filmList/filmList.wxml"/>
  2. <template is="filmList" data="{{films: films, hasMore: hasMore, showLoading: showLoading, start: start, windowHeight: windowHeight}}"/>

在popular.wcss中插入一下代码引入组件样式:

import "../../component/filmList/filmList.wxss";
  • import 引入组件(模板)
  • template 使用组件(模板) data属性可以给模板传入数据
消息提示
结构
  1. <template name="message">
  2. <view class="message-area" hidden="{{message.visiable ? false : true}}">
  3. <view class="message">
  4. <view class="message-icon message-icon-{{message.icon}}"></view>
  5. <view class="message-content">{{message.content}}</view>
  6. </view>
  7. </view>
  8. </template>
样式
  1. @import "../../component/filmList/filmList.wxss";
  2. .message-area {
  3. position: fixed;
  4. width: 100%;
  5. height: 100%;
  6. z-index: 99;
  7. }
  8. .message {
  9. box-sizing: border-box;
  10. position: fixed;
  11. z-index: 999;
  12. left: 50%;
  13. top: 50%;
  14. width: 200rpx;
  15. height: 200rpx;
  16. padding: 30rpx;
  17. margin-top: -100rpx;
  18. margin-left: -100rpx;
  19. display: flex;
  20. flex-wrap: wrap;
  21. justify-content: center;
  22. border-radius: 16rpx;
  23. background-color: rgba(0, 0, 0, .75);
  24. color: #fff;
  25. animation: fadeIn .3s;
  26. }
  27. .message-icon {
  28. height: 100rpx;
  29. width: 100rpx;
  30. background-position: center;
  31. background-repeat: no-repeat;
  32. background-size: 100rpx;
  33. }
  34. .message-icon-success {
  35. background-image: url('http://139.196.214.241:8093/cdn/images/weui-success-icon.png');
  36. }
  37. .message-icon-warning {
  38. background-image: url('http://139.196.214.241:8093/cdn/images/weui-warning-icon.png');
  39. }
  40. .message-icon-info {
  41. background-image: url('http://139.196.214.241:8093/cdn/images/weui-info-icon.png');
  42. }
  43. .message-content {
  44. margin-top: 15rpx;
  45. text-align: center;
  46. }
逻辑
  1. module.exports = {
  2. show: function(cfg) {
  3. var that = this
  4. that.setData({
  5. message: {
  6. content: cfg.content,
  7. icon: cfg.icon,
  8. visiable: true
  9. }
  10. })
  11. if (typeof cfg.duration !== 'undefined') {
  12. setTimeout(function(){
  13. that.setData({
  14. message: {
  15. visiable: false
  16. }
  17. })
  18. }, cfg.duration)
  19. }
  20. },
  21. hide: function() {
  22. var that = this
  23. that.setData({
  24. message: {
  25. visiable: true
  26. }
  27. })
  28. }
  29. }
使用方法

以search(搜索)页面为例

在search.wxml中插入以下代码引入组件结构:

  1. <import src="../../component/message/message.wxml"/>
  2. <template is="message" data="{{message: message}}"/>

在search.wcss中插入一下代码引入组件样式:

@import "../../component/message/message.wxss";

在search.js中插入一下代码引入组件逻辑:

  1. var message = require('../../component/message/message')
  2. message.show.call(that,{
  3. content: '请输入内容',
  4. icon: 'info',
  5. duration: 1500
  6. })
  • import 引入组件(模板)
  • template 使用组件(模板) data属性可以给模板传入数据
  • require 引入文件中 module.exports导出的数据或方法
  • 调用方法:message.show.call(cfg)
第二步 编写公共脚本  请求接口

列表:

  • fetchFilms:获取电影列表(热映、待映、排行、搜索结果页面)
  • fetchFilmDetail:获取电影详情
  • fetchPersonDetail:获取人物详情
  • search:搜索关键词或是类型(返回的是电影列表)
  1. var config = require('./config.js')
  2. module.exports = {
  3. fetchFilms: function(url, city, start, count, cb) {
  4. var that = this
  5. if (that.data.hasMore) {
  6. fetch(url + '?city=' + config.city + '&start=' + start + '&count=' + count).then(function(response){
  7. response.json().then(function(data){
  8. if(data.subjects.length === 0){
  9. that.setData({
  10. hasMore: false,
  11. })
  12. }else{
  13. that.setData({
  14. films: that.data.films.concat(data.subjects),
  15. start: that.data.start + data.subjects.length,
  16. showLoading: false
  17. })
  18. }
  19. typeof cb == 'function' && cb(res.data)
  20. })
  21. })
  22. }
  23. },
  24. fetchFilmDetail: function(url, id, cb) {
  25. var that = this;
  26. fetch(url + id).then(function(response){
  27. response.json().then(function(data){
  28. that.setData({
  29. showLoading: false,
  30. filmDetail: data
  31. })
  32. wx.setNavigationBarTitle({
  33. title: data.title
  34. })
  35. typeof cb == 'function' && cb(data)
  36. })
  37. })
  38. },
  39. fetchPersonDetail: function(url, id, cb) {
  40. var that = this;
  41. fetch(url + id).then(function(response){
  42. response.json().then(function(data){
  43. that.setData({
  44. showLoading: false,
  45. personDetail: data
  46. })
  47. wx.setNavigationBarTitle({
  48. title: data.name
  49. })
  50. typeof cb == 'function' && cb(data)
  51. })
  52. })
  53. },
  54. search: function(url, keyword, start, count, cb){
  55. var that = this
  56. var url = decodeURIComponent(url)
  57. if (that.data.hasMore) {
  58. fetch(url + keyword + '&start=' + start + '&count=' + count).then(function(response){
  59. response.json().then(function(data){
  60. if(data.subjects.length === 0){
  61. that.setData({
  62. hasMore: false,
  63. showLoading: false
  64. })
  65. }else{
  66. that.setData({
  67. films: that.data.films.concat(data.subjects),
  68. start: that.data.start + data.subjects.length,
  69. showLoading: false
  70. })
  71. wx.setNavigationBarTitle({
  72. title: keyword
  73. })
  74. }
  75. typeof cb == 'function' && cb(res.data)
  76. })
  77. })
  78. }
  79. }
  80. }
项目配置

city:城市
count:数量

  1. module.exports = {
  2. city: '杭州',
  3. count: 20
  4. }
第三步 编写页面
popular(热映)页面

这里以热映页面为例
待映、口碑排行、搜索结果页面可以以此类推

  • popular.json

配置窗口标题以及允许下拉刷新

  1. {
  2. "navigationBarTitleText": "正在热映",
  3. "enablePullDownRefresh": true
  4. }
  • popular.wxml

直接引入电影列表组件 与coming(待映)页、top(口碑排行)页、搜索结果页相同

  1. <import src="../../component/filmList/filmList.wxml"/>
  2. <template is="filmList" data="{{films: films, hasMore: hasMore, showLoading: showLoading, start: start, windowHeight: windowHeight}}"/>
  • popular.wxss
@import "../../component/filmList/filmList.wxss";
  • popular.js
  • 数据说明
    • films:电影列表
    • hasmore:上拉加载时是否还有更多数据
    • showLoading:是否显示loading动画
    • start:数据开始位置,用于上拉加载(每次累加)
    • windowHeight: 获取窗口高度,用于给scroll-view加高度(小程序中样式好像不能获取到窗口高度,用100%也没用,所以用js获取)
  • 页面事件
    • onLoad:页面载入,通过引入的fetch请求网络接口获取电影列表
      douban.fetchFilms.call(that, url, config.city, that.data.start, config.count)
    • onShow:页面显示,通过 wx.getSystemInfo() 获取窗口高度
    • scroll:scroll-view滚动事件
    • scrolltolower:滚动到底部触发的事件,即上拉加载更多数据。调用载入时请求的方法(此时start的值为20)
      douban.fetchFilms.call(that, url, config.city, that.data.start, config.count)
    • onPullDownRefresh:下拉刷新,初始化数据、显示加载动画并再次调用数据
    • viewFilmDetail:查看电影详情,通过e.currentTarget.dataset 获取标签中的data-*的数据,然后在路径中传递id给filmDetail页面
    • viewFilmByTag:点击标签(类型)时进入对应类型的搜索页
  1. var douban = require('../../comm/script/fetch')
  2. var config = require('../../comm/script/config')
  3. var url = 'https://api.douban.com/v2/movie/in_theaters'
  4. var searchByTagUrl = 'https://api.douban.com/v2/movie/search?tag='
  5. Page({
  6. data: {
  7. films: [],
  8. hasMore: true,
  9. showLoading: true,
  10. start: 0,
  11. windowHeight: 0
  12. },
  13. onLoad: function() {
  14. var that = this
  15. douban.fetchFilms.call(that, url, config.city, that.data.start, config.count)
  16. },
  17. onShow: function() {
  18. var that = this
  19. wx.getSystemInfo({
  20. success: function(res) {
  21. that.setData({
  22. windowHeight: res.windowHeight*2
  23. })
  24. }
  25. })
  26. },
  27. scroll: function(e) {
  28. console.log(e)
  29. },
  30. scrolltolower: function() {
  31. var that = this
  32. douban.fetchFilms.call(that, url, config.city, that.data.start, config.count)
  33. },
  34. onPullDownRefresh: function() {
  35. var that = this
  36. that.setData({
  37. films: [],
  38. hasMore: true,
  39. showLoading: true,
  40. start: 0
  41. })
  42. douban.fetchFilms.call(that, url, config.city, that.data.start, config.count)
  43. },
  44. viewFilmDetail: function(e) {
  45. var data = e.currentTarget.dataset;
  46. wx.navigateTo({
  47. url: "../filmDetail/filmDetail?id=" + data.id
  48. })
  49. },
  50. viewFilmByTag: function(e) {
  51. var data = e.currentTarget.dataset
  52. var keyword = data.tag
  53. wx.navigateTo({
  54. url: '../searchResult/searchResult?url=' + encodeURIComponent(searchByTagUrl) + '&keyword=' + keyword
  55. })
  56. }
  57. })
filmDetail(电影详情)页面

这里以电影页面为例
人物详情页面可以以此类推

  • filmDetail.json

配置窗口标题

  1. {
  2. "navigationBarTitleText": "电影详情"
  3. }
  • filmDetail.wxml
  1. <view class="container">
  2. <block wx:if="{{showLoading}}">
  3. <view class="loading">玩命加载中…</view>
  4. </block>
  5. <block wx:else>
  6. <!-- fd: film detail -->
  7. <view class="fd-hd">
  8. <view class="fd-hd-bg" style="background-image: url({{filmDetail.images.large}})"></view>
  9. <image src="{{filmDetail.images.large}}" class="fd-cover"></image>
  10. <view class="fd-intro">
  11. <view class="fd-title">{{filmDetail.title}}</view>
  12. <view class="fd-intro-txt">导演:{{filmDetail.directors[0].name}}</view>
  13. <view class="fd-intro-txt">
  14. 演员:
  15. <block wx:for="{{filmDetail.casts}}" wx:for-item="filmDetailCastItem" wx:for-index="filmDetailCastIndex" wx:key="filmDetailCastItem">
  16. {{filmDetailCastItem.name}}
  17. <block wx:if="{{filmDetailCastIndex !== filmDetail.casts.length - 1}}">/</block>
  18. </block>
  19. </view>
  20. <view class="fd-intro-txt">豆瓣评分:
  21. <block wx:if="{{filmDetail.rating.average == 0}}">
  22. 暂无评分
  23. </block>
  24. <block wx:else>
  25. {{filmDetail.rating.average}}分
  26. </block>
  27. </view>
  28. <view class="fd-intro-txt">上映年份:{{filmDetail.year}}年</view>
  29. </view>
  30. </view>
  31. <view class="fd-data">
  32. <view class="fd-data-item">
  33. <view class="fd-data-num">{{filmDetail.collect_count}}</view>
  34. <view class="fd-data-title">看过</view>
  35. </view>
  36. <view class="fd-data-item">
  37. <view class="fd-data-num">{{filmDetail.wish_count}}</view>
  38. <view class="fd-data-title">想看</view>
  39. </view>
  40. <view class="fd-data-item">
  41. <view class="fd-data-num">{{filmDetail.ratings_count}}</view>
  42. <view class="fd-data-title">评分人数</view>
  43. </view>
  44. </view>
  45. <view class="fd-bd">
  46. <view class="fd-bd-title">剧情简介</view>
  47. <view class="fd-bd-intro">{{filmDetail.summary}}</view>
  48. <view class="fd-bd-title">导演/演员</view>
  49. <view class="fd-bd-person">
  50. <view class="fd-bd-person-item" data-id="{{filmDetail.directors[0].id}}" bindtap="viewPersonDetail">
  51. <image class="fd-bd-person-avatar" src="{{filmDetail.directors[0].avatars.medium}}"></image>
  52. <view class="fd-bd-person-name">{{filmDetail.directors[0].name}}</view>
  53. <view class="fd-bd-person-role">导演</view>
  54. </view>
  55. <block wx:for="{{filmDetail.casts}}" wx:for-item="filmDetailCastItem" wx:key="filmDetailCastItem">
  56. <view class="fd-bd-person-item" data-id="{{filmDetailCastItem.id}}" bindtap="viewPersonDetail">
  57. <image class="fd-bd-person-avatar" src="{{filmDetailCastItem.avatars.medium}}"></image>
  58. <view class="fd-bd-person-name">{{filmDetailCastItem.name}}</view>
  59. <view class="fd-bd-person-role">演员</view>
  60. </view>
  61. </block>
  62. </view>
  63. <view class="fd-bd-title">标签</view>
  64. <view class="fd-bd-tag">
  65. <block wx:for="{{filmDetail.genres}}" wx:for-item="filmDetailTagItem" wx:key="filmDetailTagItem">
  66. <view class="fd-bd-tag-item" data-tag="{{filmDetailTagItem}}" catchtap="viewFilmByTag">{{filmDetailTagItem}}</view>
  67. </block>
  68. </view>
  69. </view>
  70. </block>
  71. </view>
  • filmDetail.wxss
  1. @import "../../comm/style/animation.wxss";
  2. .fd-hd {
  3. position: relative;
  4. width: 100%;
  5. height: 600rpx;
  6. display: flex;
  7. justify-content: center;
  8. align-content: center;
  9. overflow: hidden;
  10. }
  11. .fd-hd:before {
  12. content: '';
  13. display: block;
  14. position: absolute;
  15. z-index: 1;
  16. width: 100%;
  17. height: 600rpx;
  18. background-color: rgba(0, 0, 0, .6);
  19. }
  20. .fd-hd-bg {
  21. position: absolute;
  22. z-index: 0;
  23. width: 100%;
  24. height: 600rpx;
  25. background-size: cover;
  26. background-position: center;
  27. filter: blur(30rpx);
  28. }
  29. .fd-cover {
  30. z-index: 2;
  31. width: 300rpx;
  32. height: 420rpx;
  33. margin-top: 80rpx;
  34. border-radius: 8rpx;
  35. box-shadow: 0 30rpx 150rpx rgba(255, 255, 255, .3) } .fd-intro { z-index: 2;
  36. width: 320rpx;
  37. margin-top: 80rpx;
  38. margin-left: 40rpx;
  39. color: #fff;
  40. }
  41. .fd-title {
  42. margin-bottom: 30rpx;
  43. font-size: 42rpx;
  44. }
  45. .fd-intro-txt {
  46. margin-bottom: 18rpx;
  47. color: #eee;
  48. }
  49. .fd-data {
  50. display: flex;
  51. height: 150rpx;
  52. justify-content: space-around;
  53. align-items: center;
  54. border-bottom: 1px solid #f4f4f4;
  55. }
  56. .fd-data-item {
  57. width: 33.33%;
  58. text-align: center;
  59. }
  60. .fd-data-item {
  61. border-left: 1px solid #eee;
  62. }
  63. .fd-data-item:first-child {
  64. border-left: none;
  65. }
  66. .fd-data-num {
  67. font-size: 40rpx;
  68. font-weight: 100;
  69. color: #444;
  70. }
  71. .fd-data-title {
  72. color: #999;
  73. }
  74. .fd-bd {
  75. padding: 0 40rpx 40rpx;
  76. }
  77. .fd-bd-title {
  78. padding-left: 20rpx;
  79. margin-top: 40rpx;
  80. margin-bottom: 20rpx;
  81. font-size: 32rpx;
  82. font-weight: bold;
  83. color: #444;
  84. border-left: 10rpx solid #47a86c;
  85. }
  86. .fd-bd-intro {
  87. text-align: justify;
  88. line-height: 1.5;
  89. color: #666;
  90. }
  91. .fd-bd-tag {
  92. display: flex;
  93. }
  94. .fd-bd-tag-item {
  95. padding: 5rpx 10rpx;
  96. margin-right: 15rpx;
  97. border: 1px solid #ccc;
  98. border-radius: 10rpx;
  99. color: #666;
  100. }
  101. .fd-bd-person {
  102. display: flex;
  103. width: 100%;
  104. height: 480rpx;
  105. overflow-x: scroll;
  106. overflow-y: hidden;
  107. }
  108. .fd-bd-person-item {
  109. margin-left: 20rpx;
  110. text-align: center;
  111. }
  112. .fd-bd-person-item:first-child {
  113. margin-left: 0;
  114. }
  115. .fd-bd-person-avatar {
  116. width: 280rpx;
  117. height: 400rpx;
  118. }
  119. .fd-bd-person-name {
  120. color: #666;
  121. }
  122. .fd-bd-person-role {
  123. color: #999 }
  • filmDetail.js
  • 数据说明
    • filmDetail:电影详情数据
    • showLoading:是否显示loading动画
  • 页面事件
    • onLoad:页面载入,获取从电影列表传入的id (在options中),通过fetch请求网络接口获取电影详情
      douban.fetchFilmDetail.call(that, url, id)
    • viewPersonDetail:查看人物详情,通过e.currentTarget.dataset 获取标签中的data-*的数据,然后在路径中传递id给personDetail页面
    • viewFilmByTag:点击标签(类型)时进入对应类型的搜索页
  1. var douban = require('../../comm/script/fetch')
  2. var url = 'https://api.douban.com/v2/movie/subject/'
  3. var searchByTagUrl = 'https://api.douban.com/v2/movie/search?tag='
  4. Page({
  5. data: {
  6. filmDetail: {},
  7. showLoading: true
  8. },
  9. onLoad: function(options) {
  10. var that = this
  11. var id = options.id
  12. douban.fetchFilmDetail.call(that, url, id)
  13. },
  14. viewPersonDetail: function(e) {
  15. var data = e.currentTarget.dataset;
  16. wx.redirectTo({
  17. url: '../personDetail/personDetail?id=' + data.id
  18. })
  19. },
  20. viewFilmByTag: function(e) {
  21. var data = e.currentTarget.dataset
  22. var keyword = data.tag
  23. wx.navigateTo({
  24. url: '../searchResult/searchResult?url=' + encodeURIComponent(searchByTagUrl) + '&keyword=' + keyword
  25. })
  26. }
  27. })
search(搜索)页面
  • search.json

配置窗口标题

  1. {
  2. "navigationBarTitleText": "搜索"
  3. }
  • search.wxml

引用了message组件,当没有输入内容时给出提示

  1. <import src="../../component/message/message.wxml"/>
  2. <template is="message" data="{{message: message}}"/>
  3. <view class="search-hd">
  4. <view class="search-area">
  5. <form bindsubmit="search">
  6. <view class="search-type" bindtap="changeSearchType">{{searchType == 0 ? '默认' : '类型'}}</view>
  7. <input class="search-txt" name="keyword" auto-focus placeholder="{{searchType == 0 ? '请输入电影标题、演员或导演' : '请输入影片类型,如:爱情、喜剧'}}"/>
  8. <button class="search-btn" formType="submit">搜索</button>
  9. </form>
  10. </view>
  11. <view class="search-keyword">
  12. <view class="search-keyword-title">热门搜索</view>
  13. <view wx:for="{{hotKeyword}}" wx:for-item="hotKeywordItem" wx:key="hotKeywordItem" class="search-keyword-item" data-keyword="{{hotKeywordItem}}" bindtap="searchByKeyword">{{hotKeywordItem}}</view>
  14. <view class="search-keyword-title">热门标签</view>
  15. <view wx:for="{{hotTag}}" wx:for-item="hotTagItem" wx:key="hotTagItem" class="search-keyword-item" data-keyword="{{hotTagItem}}" bindtap="searchByTag">{{hotTagItem}}</view>
  16. </view>
  17. </view>
  • search.js
  • 数据说明
    • searchType:搜索类型 0为关键词,1为类型(标签)
    • hotKeyword:热门关键词
    • hotTag:热门标签
  • 页面事件
    • changeSearchType:改变搜索类型,通过wx.showActionSheet
    • search:搜索表单提交事件,如果没有输入内容,则自定义消息组件的show方法即message.show.call(cfg)来提示用户,有内容则通过e.detail.value来获取表单的数据,并传递给searchDetail(搜索结果页)
    • searchByKeyword:点击关键词时进入对应类型的搜索页
    • viewFilmByTag:点击标签(类型)时进入对应类型的搜索页
  1. var message = require('../../component/message/message')
  2. var douban = require('../../comm/script/fetch')
  3. var url = ['https://api.douban.com/v2/movie/search?q=', 'https://api.douban.com/v2/movie/search?tag=']
  4. Page({
  5. data:{
  6. searchType: 0,
  7. hotKeyword: ['功夫熊猫', '烈日灼心', '摆渡人', '长城', '我不是潘金莲', '这个杀手不太冷', '驴得水', '海贼王之黄金城', '西游伏妖片', '我在故宫修文物', '你的名字'],
  8. hotTag: ['动作', '喜剧', '爱情', '悬疑']
  9. },
  10. changeSearchType: function() {
  11. var types = ['默认', '类型'];
  12. var that = this
  13. wx.showActionSheet({
  14. itemList: types,
  15. success: function(res) {
  16. if (!res.cancel) {
  17. that.setData({
  18. searchType: res.tapIndex
  19. })
  20. }
  21. }
  22. })
  23. },
  24. search: function(e) {
  25. var that = this
  26. var keyword = e.detail.value.keyword
  27. if (keyword == '') {
  28. message.show.call(that,{
  29. content: '请输入内容',
  30. icon: 'info',
  31. duration: 1500
  32. })
  33. return false
  34. } else {
  35. wx.navigateTo({
  36. url: '../searchResult/searchResult?url=' + encodeURIComponent(url[that.data.searchType]) + '&keyword=' + keyword
  37. })
  38. }
  39. },
  40. searchByKeyword: function(e) {
  41. var that = this
  42. var keyword = e.currentTarget.dataset.keyword
  43. wx.navigateTo({
  44. url: '../searchResult/searchResult?url=' + encodeURIComponent(url[0]) + '&keyword=' + keyword
  45. })
  46. },
  47. searchByTag: function(e) {
  48. var that = this
  49. var keyword = e.currentTarget.dataset.keyword
  50. wx.navigateTo({
  51. url: '../searchResult/searchResult?url=' + encodeURIComponent(url[1]) + '&keyword=' + keyword
  52. })
  53. }
  54. })
附录
UI
  • 页面加载

    screenshot-1
  • 电影列表

    screenshot-2
  • 下拉刷新

    screenshot-3
  • 电影详情

    screenshot-4
  • 任务详情

    screenshot-5
  • 搜索

    screenshot-6
  • 搜索结果 (关键词搜索)

    screenshot-7
  • 搜索结果 (标签/类型搜索)

    screenshot-8
  • 信息提示

    screenshot-9
思维导图

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号