黑马本地生活(列表页面,详情页面)

🏡浩泽学编程个人主页
🔥 推荐专栏《深入浅出SpringBoot》《java项目分享》
《RabbitMQ》《Spring》《SpringMVC》

🛸学无止境,不骄不躁,知行合一

文章目录


前言

在学习微信小程序时,黑马给出了列表页面讲解,这里我再补充一个黑马没有讲诉的商家详情页面代码。


一、列表页面

功能

  • 页面导航并传参
  • 上拉触底时加载下一页数据
  • 下拉刷新列表数据

列表页面API

实现

效果图:

shoplist.wxml:

html 复制代码
<include src="/includes/search-bar.wxml"/>
  <view class="cells">
    <navigator class="item" wx:for="{{shopList}}" wx:key="id" url="/pages/detail/detail?id={{count}}&did={{index}}">
      <image src="{{item.images[0]}}" mode="aspectFill"/>
      <view class="meta">
        <text class="name">{{item.name}}</text>
        <text class="phone">电话:{{tools.splitPhone(item.phone) || 'none'}}</text>
        <text class="address">地址:{{item.address}}</text>
        <text class="hours">营业时间:{{item.businessHours}}</text>
      </view>
      <view class="score">{{item.score || 'none'}}</view>
  </navigator>
</view>

<wxs src="../../utils/tools.wxs" module="tools"></wxs>

search-bar.xml:

html 复制代码
<view class="weui-search-bar">
  <view class="weui-search-bar__form">
    <view class="weui-search-bar__box">
      <icon class="weui-icon-search_in-box" type="search" size="14"/>
      <input type="text" class="weui-search-bar__input" placeholder="搜索" value="{{searchText}}" focus="{{searchShowed}}" bindinput="searchChangeHandle" bindconfirm="searchHandle"/>
      <view class="weui-icon-clear" wx:if="{{searchText}}" bindtap="clearSearchHandle">
        <icon type="clear" size="14"/>
      </view>
    </view>
    <label class="weui-search-bar__label" hidden="{{searchShowed}}" bindtap="showSearchHandle">
      <icon class="weui-icon-search" type="search" size="14"/>
      <view class="weui-search-bar__text">搜索</view>
    </label>
  </view>
  <view class="weui-search-bar__cancel-btn" hidden="{{!searchShowed}}" bindtap="hideSearchHandle">取消</view>
</view>
<!-- <view class="weui-cells searchbar-result" wx:if="{{searchText}}">
  <navigator url="" class="weui-cell" hover-class="weui-cell_active">
    <view class="weui-cell__bd">暂时未实现</view>
  </navigator>
</view> -->
js 复制代码
// pages/shoplist/shoplist.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    count: 0,
    query: {},
    shopList: [],
    page: 1,
    pageSize: 10,
    total: 0,
    isloading: false
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    this.setData({
      query: options
    })
    this.getShopList()
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    wx.setNavigationBarTitle({
      title: this.data.query.title
    })
  },

  // 以分页的形式获取商铺列表数据的方法
  getShopList(cb) {
    this.setData({
      isloading: true
    })
    // 展示 loading 效果
    wx.showLoading({
      title: '数据加载中...'
    })

    wx.request({
      url: `https://applet-base-api-t.itheima.net/categories/${this.data.query.id}/shops`,
      method: 'GET',
      data: {
        _page: this.data.page,
        _limit: this.data.pageSize
      },
      success: (res) => {
        this.setData({
          shopList: [...this.data.shopList, ...res.data],
          total: res.header['X-Total-Count'] - 0,
          count: this.data.query.id
        })
      },
      complete: () => {
        // 隐藏 loading 效果
        wx.hideLoading()
        this.setData({ isloading: false })
        // wx.stopPullDownRefresh()
        cb && cb()
      }
    })
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {
        // 需要重置关键的数据
        this.setData({
          page: 1,
          shopList: [],
          total: 0
        })
        // 重新发起数据请求
        this.getShopList(() => {
          wx.stopPullDownRefresh()
        })
  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {
    if (this.data.page * this.data.pageSize >= this.data.total) {
      // 证明没有下一页的数据了
      return wx.showToast({
        title: '数据加载完毕!',
        icon: 'none'
      })
    }
    // 判断是否正在加载其他数据
    if (this.data.isloading) return
    // 页码值 +1
    this.setData({
      page: this.data.page + 1
    })

    // 获取下一页数据
    this.getShopList()
  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})
css 复制代码
.shop-item {
  display: flex;
  padding: 15rpx;
  border: 1rpx solid #efefef;
  border-radius: 8rpx;
  margin: 15rpx;
  box-shadow: 1rpx 1rpx 15rpx #ddd;
}

.thumb image {
  width: 250rpx;
  height: 250rpx;
  display: block;
  margin-right: 15rpx;
}

.info {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  font-size: 24rpx;
}

.shop-title {
  font-weight: bold;
}
.cells {
  background-color: #fff;
}

.cells .item {
  display: flex;
  align-items: flex-start;
  border-bottom: 1rpx solid #eee;
}

.cells .item image {
  width: 160rpx;
  height: 160rpx;
  margin: 20rpx;
}

.cells .item .meta {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 10rpx 0;
  font-size: 30rpx;
}

.cells .item .meta .name {
  color: #234;
  font-size: 28rpx;
}

.cells .item .meta .phone,
.cells .item .meta .address {
  color: #678;
  font-size: 24rpx;
}

.cells .item .meta .hours {
  /*color: #ff69b4;*/
  color: #456;
  font-size: 22rpx;
}

.cells .item .score {
  margin: 20rpx 20rpx 0 -40rpx;
  padding: 0 10rpx;
  background-color: #ee523d;
  border-radius: 30rpx;
  color: #fff;
  font-size: 24rpx;
  text-align: center;
}

.loadmore {
  color: #888;
  font-size: 30rpx;
  line-height: 100rpx;
  text-align: center;
}

.loadmore.loading::before {
  content: '';
  width: 40rpx;
  height: 40rpx;
  margin-top: -10rpx;
  margin-right: 10rpx;
  display: inline-block;
  vertical-align: middle;
  animation: loading 1s steps(12) infinite;
  background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat;
  background-size: 100%
}

@keyframes loading {
  from {
    transform: rotate(0deg)
  }
  to {
    transform: rotate(-360deg)
  }
}

shop.json:

json 复制代码
{
  "usingComponents": {},
  "onReachBottomDistance": 200,
  "enablePullDownRefresh": true,
  "backgroundColor": "#efefef",
  "backgroundTextStyle": "dark"
}

二、详情页面

分析

大家可以看到在列表页面,黑马提供的API中返回的数据是有详情页面的信息的:

所以要添加详情页面就是解决如何提取这些信息,现在知道的是在获取某一类列表页面时,https://applet-base-api-t.itheima.net/categories/id/shops,只需要将这个接口中id换成1、2、3...,并且返回的数据包含了详情的信息,所以我们现在将id参数继续传给详情页面,就能在加载详情页面根据这个api继续获取数据(重复获取了),但是要知道获取哪个商家的详情,还需要参数,根据获取数据看到规律:就是用wx-for渲染列表页面时,每个元素的index值一样。

实现

效果图:

detail.wxml:

html 复制代码
<!--pages/detail/detail.wxml-->
<swiper class="slides" indicator-dots="{{shop.images.length > 1}}" indicator-color="#bcc0c9" indicator-active-color="#3a4861">
  <swiper-item wx:for="{{shop.images}}" wx:key="id">
    <image src="{{item}}" mode="aspectFill" bindtap="previewHandle" data-src="{{item}}"/>
  </swiper-item>
</swiper>

<view class="heading" wx:if="{{shop.name}}">
  <text class="name">{{shop.name}}</text>
  <text class="phone">电话:{{shop.phone || 'none'}}</text>
  <text class="address">地址:{{shop.address}}</text>
  <text class="hours">营业时间:{{shop.businessHours}}</text>
  <view class="score" wx:if="{{item.score}}">{{item.score}}</view>
</view>

<view class="introduction" wx:if="{{shop.introduction}}">
  <text>{{shop.introduction}}</text>
</view>

<view class="comments" wx:if="{{shop.comments.length}}">
  <view class="item" wx:for="{{shop.comments}}" wx:key="*this">
    <text class="name">{{item.name}}</text>
    <text class="date">{{item.date}}</text>
    <text class="rating">{{item.rating}}</text>
    <text class="content">{{item.content}}</text>
    <view class="images">
      <image wx:for="{{item.images}}" wx:key="*this" src="{{utils.size(item)}}"/>
    </view>
  </view>
</view>

<wxs module="utils">
  module.exports = {
    size: function (input) {
      return input.replace('w.h', '100.100')
    }
  }
</wxs>

shop.wxss:

css 复制代码
/* pages/detail/detail.wxss */
.slides {
  height: 580rpx;
}

.slides image {
  min-width: 100%;
  height: 100%;
}

.heading {
  display: flex;
  flex-direction: column;
  padding: 20rpx 30rpx;
  background-color: #fff;
  color: #567;
  font-size: 24rpx;
}

.heading .name {
  font-size: 40rpx;
  color: #234;
}

.heading .score {
  position: absolute;
  top: 20rpx;
  right: 20rpx;
  padding: 0 10rpx;
  background-color: #ee523d;
  border-radius: 30rpx;
  color: #fff;
  font-size: 24rpx;
  text-align: center;
}

.introduction {
  margin-top: 20rpx;
  padding: 30rpx;
  background-color: #fff;
  color: #456;
  font-size: 24rpx;
  line-height: 2;
}

.comments {
  margin-top: 20rpx;
  padding: 20rpx;
  background-color: #fff;
  color: #345;
  font-size: 24rpx;
}

.comments .item {
  display: flex;
  position: relative;
  flex-direction: column;
  padding: 20rpx;
  border-bottom: 1rpx solid #eee;
}

.comments .item .name {
  margin-top: 20rpx;
  font-size: 36rpx;
}

.comments .item .date {
  align-self: flex-end;
  margin: -40rpx 0 20rpx;
  color: #567;
}

.comments .item .rating {
  position: absolute;
  top: 20rpx;
  right: 10rpx;
  color: #ee523d;
}

.comments .item image {
  width: 110rpx;
  height: 110rpx;
  margin: 10rpx;
}
js 复制代码
const fetch = require('../../utils/fetch.js')

Page({
  /**
   * 页面的初始数据
   */
  data: {
    shop: []
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad (options) {
    fetch(`/categories/${options.id}/shops`)
      .then(res => {
        this.setData({ shop: res.data[options.did] })
        wx.setNavigationBarTitle({ title: res.data[options.did].name })
      })
  },

  previewHandle (e) {
    wx.previewImage({
      current: e.target.dataset.src,
      urls: this.data.shop.images
    })
  }
})

fetch.js:

js 复制代码
const app = getApp()

module.exports = (url, data, method = 'GET', header = {}) => {
  wx.showLoading({ title: 'Loading...' })
  return new Promise((resolve, reject) => {
    wx.request({
      url: app.config.apiBase + url,
      data,
      header,
      method,
      dataType: 'json',
      success: resolve,
      fail: reject,
      complete: wx.hideLoading
    })
  })
}
json 复制代码
{
  "usingComponents": {},
  "navigationBarTitleText": "详情"
}

app.js加入:

js 复制代码
  config: {
    apiBase: 'https://applet-base-api-t.itheima.net'
  }

总结

以上就是本地生活案例讲解。

相关推荐
EricWang13589 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning9 分钟前
React.lazy() 懒加载
前端·react.js·前端框架
让学习成为一种生活方式15 分钟前
R包下载太慢安装中止的解决策略-R语言003
java·数据库·r语言
web行路人19 分钟前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
晨曦_子画20 分钟前
编程语言之战:AI 之后的 Kotlin 与 Java
android·java·开发语言·人工智能·kotlin
假装我不帅40 分钟前
asp.net framework从webform开始创建mvc项目
后端·asp.net·mvc
超雄代码狂41 分钟前
ajax关于axios库的运用小案例
前端·javascript·ajax
南宫生43 分钟前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
神仙别闹43 分钟前
基于ASP.NET+SQL Server实现简单小说网站(包括PC版本和移动版本)
后端·asp.net
长弓三石1 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙