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

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

总结

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

相关推荐
Metaphor69221 小时前
Java 旋转 PDF 页面:使用 Spire.PDF 实现高效页面处理
java·经验分享·pdf
Terio_my21 小时前
Spring Boot 整合 Elasticsearch
spring boot·后端·elasticsearch
哈利路亚胡辣汤21 小时前
spring多数据源配置
java·spring·mybatis
卷Java21 小时前
智慧停车大屏数据分析与设计文档
java·大数据·人工智能·数据分析
行者..................21 小时前
手动编译 OpenCV 4.1.0 源码,生成 ARM64 动态库 (.so),然后在 Petalinux 中打包使用。
前端·webpack·node.js
阑梦清川21 小时前
linux基础--文件描述符&&输出重定向的理解
后端
聪明的笨猪猪1 天前
Java SE “JDK1.8新特性”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
小爱同学_1 天前
一次面试让我重新认识了 Cursor
前端·面试·程序员
Excuse_lighttime1 天前
除自身以外数组的乘积
java·数据结构·算法·leetcode·eclipse·动态规划