在学习微信小程序时,黑马给出了列表页面讲解,这里我再补充一个黑马没有讲诉的商家详情页面代码。
shoplist.wxml:
<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:
<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>
// 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() {
}
})
.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:
{
"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值一样。
<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:
/* 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;
}
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:
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
})
})
}
{
"usingComponents": {},
"navigationBarTitleText": "详情"
}
app.js加入:
config: {
apiBase: 'https://applet-base-api-t.itheima.net'
}
以上就是本地生活案例讲解。