微信小程序案例 - 本地生活(列表页面)

一、前言

随着微信小程序的普及,越来越多的生活服务类应用开始基于微信小程序进行开发。其中,"本地生活"类小程序(如美食、团购、周边游等)因其贴近用户日常需求而广受欢迎。

本篇文章将以一个 "本地生活列表页面" 的实际案例为例,手把手带你实现一个完整的 微信小程序本地生活类首页列表页面,包括:

✅ 页面结构设计

✅ 数据绑定与渲染

✅ 列表项布局与样式优化

✅ 下拉刷新与上拉加载更多

✅ 搜索功能初步实现

✅ 真实数据模拟与静态化处理

并通过完整代码示例帮助你掌握如何在微信小程序中构建一个高性能、可扩展的本地生活类页面。

二、项目目标

我们将实现一个类似大众点评或美团风格的本地生活首页,主要包含以下功能模块:

模块 功能描述
头部搜索栏 支持关键词搜索
分类导航 如美食、外卖、电影、旅游等分类图标
商品列表 展示商家信息(图片、名称、评分、价格等)
上拉加载 支持分页加载更多商品
下拉刷新 手动刷新数据

三、项目结构说明

复制代码
project/
├── app.js
├── app.json
├── app.wxss
├── pages/
│   └── index/
│       ├── index.js
│       ├── index.json
│       ├── index.wxml
│       └── index.wxss
└── utils/
    └── mockData.js

我们使用了 mockData.js 来模拟后端接口返回的数据,便于快速开发调试。

四、页面结构搭建

✅ 1. index.wxml 结构

XML 复制代码
<view class="container">
  <!-- 搜索栏 -->
  <view class="search-bar">
    <input class="search-input" placeholder="请输入关键词搜索" bindinput="onInput"/>
  </view>

  <!-- 分类导航 -->
  <scroll-view scroll-x class="category-scroll">
    <view wx:for="{{categories}}" wx:key="id" class="category-item">
      <image src="{{item.icon}}" mode="aspectFit" class="category-icon"/>
      <text>{{item.name}}</text>
    </view>
  </scroll-view>

  <!-- 商品列表 -->
  <view class="goods-list">
    <block wx:for="{{goodsList}}" wx:key="id">
      <view class="goods-item">
        <image src="{{item.image}}" class="goods-image"/>
        <view class="goods-info">
          <text class="goods-title">{{item.title}}</text>
          <text class="goods-desc">{{item.desc}}</text>
          <text class="goods-price">¥{{item.price}}</text>
        </view>
      </view>
    </block>
  </view>

  <!-- 加载提示 -->
  <view wx:if="{{loading}}" class="loading">正在加载...</view>
</view>

✅ 2. index.wxss 样式定义

css 复制代码
.container {
  padding: 20rpx;
}

.search-bar {
  margin-bottom: 20rpx;
}

.search-input {
  height: 60rpx;
  border: 1rpx solid #ccc;
  border-radius: 8rpx;
  padding: 0 20rpx;
}

.category-scroll {
  white-space: nowrap;
  display: flex;
  overflow-x: auto;
}

.category-item {
  display: inline-block;
  text-align: center;
  margin-right: 40rpx;
  width: 120rpx;
}

.category-icon {
  width: 80rpx;
  height: 80rpx;
  margin-bottom: 10rpx;
}

.goods-list {
  border-top: 1rpx solid #eee;
}

.goods-item {
  display: flex;
  padding: 20rpx 0;
  border-bottom: 1rpx solid #eee;
}

.goods-image {
  width: 160rpx;
  height: 160rpx;
  margin-right: 20rpx;
  border-radius: 8rpx;
}

.goods-info {
  flex: 1;
  flex-direction: column;
  justify-content: space-between;
}

.goods-title {
  font-size: 28rpx;
  font-weight: bold;
}

.goods-desc {
  color: #666;
  font-size: 24rpx;
  margin-top: 10rpx;
}

.goods-price {
  color: red;
  font-size: 28rpx;
  margin-top: 10rpx;
}

.loading {
  text-align: center;
  margin-top: 20rpx;
}

五、数据绑定与交互逻辑

✅ 1. mockData.js 模拟数据

javascript 复制代码
// utils/mockData.js
module.exports = {
  categories: [
    { id: 1, name: '美食', icon: 'https://example.com/icon-food.png' },
    { id: 2, name: '外卖', icon: 'https://example.com/icon-takeout.png' },
    { id: 3, name: '电影', icon: 'https://example.com/icon-movie.png' },
    { id: 4, name: '旅游', icon: 'https://example.com/icon-travel.png' }
  ],
  goodsList: [
    { id: 1, title: '肯德基', desc: '新品套餐限时优惠', price: 29.9, image: 'https://example.com/goods1.jpg' },
    { id: 2, title: '麦当劳', desc: '经典汉堡组合', price: 35.5, image: 'https://example.com/goods2.jpg' },
    { id: 3, title: '海底捞', desc: '火锅套餐特惠', price: 98.0, image: 'https://example.com/goods3.jpg' }
  ]
};

✅ 2. index.js 逻辑控制

javascript 复制代码
const mockData = require('../../utils/mockData');

Page({
  data: {
    categories: mockData.categories,
    goodsList: [],
    loading: false,
    page: 1
  },

  onLoad() {
    this.loadGoods();
  },

  // 输入事件
  onInput(e) {
    const keyword = e.detail.value;
    console.log('输入关键字:', keyword);
    // TODO: 过滤 goodsList 或请求接口
  },

  // 加载商品数据
  loadGoods() {
    this.setData({ loading: true });
    setTimeout(() => {
      const newGoods = [...this.data.goodsList, ...mockData.goodsList];
      this.setData({
        goodsList: newGoods,
        page: this.data.page + 1,
        loading: false
      });
    }, 1000);
  },

  // 上拉加载
  onReachBottom() {
    this.loadGoods();
  },

  // 下拉刷新
  onPullDownRefresh() {
    this.setData({
      goodsList: [],
      page: 1
    });
    this.loadGoods();
    wx.stopPullDownRefresh();
  }
});

六、功能扩展建议

功能 实现方式
接入真实 API 替换 mockData.js 为 wx.request() 请求
图片懒加载 使用 mode="lazy" 或自定义组件
地理定位 调用 wx.getLocation() 获取位置
评分显示 使用自定义组件或 CSS 星级评分
骨架屏优化 使用 <skeleton> 组件提升用户体验

七、常见问题与解决方案

问题 原因 解决方案
列表不更新 数据未正确绑定 检查 setData 是否正确调用
滚动加载失效 未触发 onReachBottom 设置 page.json 中 onReachBottomDistance
图片无法加载 路径错误或跨域 使用 HTTPS 资源并检查网络权限
搜索框无响应 未绑定 bindinput 检查事件名是否拼写正确
页面样式错乱 未启用 rpx 单位 确保使用 rpx 而非 px

八、总结对比表:关键功能实现一览

功能 技术点
搜索框输入 bindinput 事件
分类滚动 scroll-view + flex
商品列表渲染 wx:for + setData
上拉加载 onReachBottom
下拉刷新 onPullDownRefresh + wx.stopPullDownRefresh
数据绑定 data + setData
模拟数据 require 引入 JSON 数据

九、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
爱勇宝11 小时前
小红花成长更新了:孩子想要什么,也应该有机会自己说出来
微信小程序·产品·小程序·云开发
greencherry_19 小时前
大连模屿石膏课模具配比全固定,调色浇注之外还缺什么?
算法·生活
andrsted20 小时前
企业培训时间难统一?练题簿让在线免费刷题与培训考核更好安排
学习·微信小程序·小程序·学习方法·刷题
拖孩20 小时前
一个人 + AI 做的小程序,今天,正式回本了
前端·后端·微信小程序
李纲明21 小时前
微信小程序 wx.uploadFile 上传失败:合法域名、临时路径与 HTTPS 证书排查
微信小程序·小程序·uploadfile·devdiy·上传失败
宝绿特塑业再生科技1 天前
改性HDPE再生颗粒在户外家具挤出发泡板材中的色差控制与高品质价值重构
经验分享·科技·学习·生活·1024程序员节·户外家具
冬奇Lab1 天前
一天一个开源项目(第247篇):wxa-runner —— 让小程序在普通浏览器里用微信官方基础库跑起来,直接接 Playwright 做无头 E2E
微信小程序·开源
andrsted1 天前
练题簿在线免费刷题:让整理过的资料,变成能反复练习的题库
学习·微信小程序·小程序·学习方法·刷题·1024程序员节
Stringzhua2 天前
向后理解,向前生活
生活
2601_967979122 天前
当代码有了温度:程序员的键盘上,藏着人间烟火
程序员·生活·技术·代码·温情