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

发布于:2025-07-16 ⋅ 阅读:(17) ⋅ 点赞:(0)

一、前言

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

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

✅ 页面结构设计
✅ 数据绑定与渲染
✅ 列表项布局与样式优化
✅ 下拉刷新与上拉加载更多
✅ 搜索功能初步实现
✅ 真实数据模拟与静态化处理

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

二、项目目标

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

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

三、项目结构说明

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 结构

<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 样式定义

.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 模拟数据

// 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 逻辑控制

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 数据

九、结语

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


网站公告

今日签到

点亮在社区的每一天
去签到