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

🏡浩泽学编程个人主页
🔥 推荐专栏《深入浅出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'
  }

总结

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

相关推荐
用户21411832636027 分钟前
dify案例分享-零代码搞定 DIFY 插件开发:小白也能上手的文生图插件实战
后端
计算机程序员小杨18 分钟前
计算机专业的你懂的:大数据毕设就选贵州茅台股票分析系统准没错|计算机毕业设计|数据可视化|数据分析
java·大数据
y1y1z22 分钟前
EasyExcel篇
java·excel
DokiDoki之父41 分钟前
多线程—飞机大战排行榜功能(2.0版本)
android·java·开发语言
阳光阴郁大boy1 小时前
一个基于纯前端技术实现的五子棋游戏,无需后端服务,直接在浏览器中运行。
前端·游戏
高山上有一只小老虎1 小时前
走方格的方案数
java·算法
whatever who cares1 小时前
Java 中表示数据集的常用集合类
java·开发语言
石小石Orz1 小时前
效率提升一倍!谈谈我的高效开发工具链
前端·后端·trae
EndingCoder1 小时前
测试 Next.js 应用:工具与策略
开发语言·前端·javascript·log4j·测试·全栈·next.js
xw51 小时前
免费的个人网站托管-PinMe篇
服务器·前端