微信小程序火车票查询实战:从请求封装到列表渲染

发布时间:2026/10/20 14:10:20
微信小程序火车票查询实战:从请求封装到列表渲染 简介这份资源是一套基于微信小程序实现的火车票查询系统源码面向具备小程序基础语法、希望练习接口调用与页面联调的开发者也可作为课程设计或毕业设计的起步模板。项目围绕车次查询、站点信息与余票展示等典型场景组织代码方便在此基础上继续扩展订单、登录等功能。压缩包共23个文件约11KB包含8个js逻辑脚本、5个json配置、5个wxss样式、4个wxml页面结构以及1个md说明文档分别承担业务逻辑、页面配置、界面样式与视图渲染等职责目录按页面与工具模块划分结构清晰。目前已有1643人学习下载。读者可从中获取完整的小程序请求封装与页面交互示例理解api与request工具模块的调用方式并参考其目录组织与配置写法快速搭建自己的查询类小程序减少从零摸索的成本。1. 从一次抢票失败说起这个火车票查询小程序到底能干什么去年春运前我帮朋友看一个抢票脚本的问题结果发现他连车次余票都查不明白——用的还是某个第三方网页接口返回的数据结构一变整个脚本就崩了。当时我就想与其依赖别人维护的接口不如自己写一个能跑通查询链路的小程序。后来在代码仓库里翻到了这个「微信小程序-火车票查询」项目它正好解决了一个很具体的需求在微信里输入出发站、到达站和日期直接拿到车次列表和余票信息不用跳来跳去。这个项目适合两类人一是想学小程序网络请求和列表渲染的新手代码结构简单跑起来就能看到数据二是需要快速搭一个查询工具原型的开发者核心逻辑抽出来就能复用。它不涉及支付和下单只做查询展示所以调试成本很低不用申请复杂的商户资质。接下来我按「能跑、能看懂、能改」的顺序把这个项目的骨架和关键实现拆一遍。2. 项目骨架与运行链路从目录结构到第一次请求成功2.1 目录结构小程序标准分层与页面组织拿到源码后先看根目录。这个项目用的是微信小程序原生框架没有引入第三方 UI 库所以目录很干净。常见结构是pages放页面、utils放工具函数、app.json做全局配置。我打开时第一眼找的是app.json里的pages数组它决定了启动页和页面路径。{ pages: [ pages/index/index, pages/result/result ], window: { navigationBarTitleText: 火车票查询, navigationBarBackgroundColor: #1E90FF } }这段配置里pages数组第一项是启动页所以打开小程序先看到查询表单。window里设了导航栏标题和背景色改颜色直接改十六进制值就行。注意pages路径不要写.js后缀否则编译会报错这是新手常踩的坑。pages/index负责输入pages/result负责展示车次列表。两个页面之间用wx.navigateTo跳转参数通过 URL 拼接传递。这种拆分方式让查询逻辑和渲染逻辑分开改起来不会互相干扰。2.2 查询表单输入校验与日期选择首页的index.wxml里放了两个输入框和一个日期选择器。出发站和到达站用input日期用picker modedate。我一般会在这里加一个非空校验防止用户直接点查询导致请求参数为空。// pages/index/index.js Page({ data: { from: , to: , date: }, onFromInput(e) { this.setData({ from: e.detail.value.trim() }); }, onDateChange(e) { this.setData({ date: e.detail.value }); }, onQuery() { const { from, to, date } this.data; if (!from || !to || !date) { wx.showToast({ title: 请填写完整, icon: none }); return; } wx.navigateTo({ url: /pages/result/result?from${from}to${to}date${date} }); } });setData是小程序更新视图的核心方法这里把输入值同步到data。onQuery里先做空值判断再用模板字符串拼 URL。注意from和to如果包含特殊字符需要encodeURIComponent处理否则跳转后参数会截断。日期选择器返回的是YYYY-MM-DD格式正好符合大多数查询接口的要求。2.3 网络请求封装wx.request 与公共配置查询请求放在result.js的onLoad里。项目里把请求域名和路径抽到了utils/config.js这样换接口时不用翻遍所有页面。// utils/config.js const BASE_URL https://api.example.com; // 替换成实际可用的查询接口 module.exports { QUERY_TRAINS: ${BASE_URL}/train/query };// pages/result/result.js const config require(../../utils/config.js); Page({ data: { trains: [], loading: true }, onLoad(options) { const { from, to, date } options; this.queryTrains(from, to, date); }, queryTrains(from, to, date) { wx.request({ url: config.QUERY_TRAINS, method: GET, data: { from, to, date }, success: (res) { if (res.data res.data.code 0) { this.setData({ trains: res.data.list, loading: false }); } else { wx.showToast({ title: 查询失败, icon: none }); } }, fail: () { wx.showToast({ title: 网络异常, icon: none }); } }); } });wx.request的data字段会自动拼成查询字符串不用手动拼接。success里先判断业务状态码再取list赋值给trains。这里有个细节如果接口返回的字段名不是list需要同步改setData的键名。fail回调处理网络层错误比如域名未配置或超时。注意小程序正式环境要求 HTTPS 域名开发时可以在开发者工具里勾选「不校验合法域名」临时绕过。2.4 列表渲染wx:for 与余票状态展示拿到数据后result.wxml用wx:for渲染车次列表。每个车次显示车次号、出发到达时间、历时和余票状态。view wx:if{{loading}}加载中.../view view wx:else view wx:for{{trains}} wx:keytrainNo classtrain-item text{{item.trainNo}}/text text{{item.fromTime}} - {{item.toTime}}/text text{{item.duration}}/text text class{{item.seatCount 0 ? has-seat : no-seat}} {{item.seatCount 0 ? 有票 : 无票}} /text /view /viewwx:key用trainNo保证列表更新时不会错位。余票状态用三元表达式切换 classhas-seat和no-seat在wxss里定义颜色。如果接口返回的余票是数字直接比较如果是字符串「有」「无」需要改判断条件。这里我一般会加一个item.seatCount的默认值防止字段缺失导致渲染空白。3. 核心模块拆解查询参数处理与数据映射3.1 车站数据本地字典与拼音匹配火车票查询有个绕不开的问题用户输入「北京」还是「北京西」项目里用了一个本地车站字典放在utils/stations.js把常用车站名和拼音缩写都列出来。// utils/stations.js const stations [ { name: 北京, code: BJP, pinyin: beijing }, { name: 北京西, code: BXP, pinyin: beijingxi }, { name: 上海, code: SHH, pinyin: shanghai }, { name: 广州, code: GZQ, pinyin: guangzhou } ]; module.exports stations;查询前先用stations.find把用户输入转成车站代码再传给接口。如果找不到匹配项就提示「车站不存在」。这个字典可以按需扩充但注意代码要和接口要求的一致不同数据源可能用不同的三字码。我一般会把字典单独维护不混在页面逻辑里方便后续替换成远程接口。3.2 日期格式化补零与接口兼容日期选择器返回的格式是YYYY-MM-DD但有些接口要求YYYYMMDD。项目里在utils/util.js写了一个转换函数。// utils/util.js function formatDate(dateStr) { return dateStr.replace(/-/g, ); } module.exports { formatDate };调用时formatDate(2025-01-01)返回20250101。如果接口要求带时间戳可以再包一层new Date(dateStr).getTime()。注意时区问题小程序运行在用户设备上new Date会按本地时区解析跨时区场景要统一用 UTC。3.3 请求参数组装从页面到接口的完整链路把前面的步骤串起来result.js里实际组装参数的逻辑是这样的const stations require(../../utils/stations.js); const { formatDate } require(../../utils/util.js); queryTrains(from, to, date) { const fromStation stations.find(s s.name from || s.pinyin from); const toStation stations.find(s s.name to || s.pinyin to); if (!fromStation || !toStation) { wx.showToast({ title: 车站名有误, icon: none }); return; } wx.request({ url: config.QUERY_TRAINS, data: { from: fromStation.code, to: toStation.code, date: formatDate(date) }, // ... 成功失败回调同上 }); }这里先做车站匹配支持中文名和拼音两种输入。find返回第一个匹配项如果有重名车站比如「北京」和「北京西」都包含「北京」需要更精确的匹配规则比如优先完全相等。日期转换放在请求前保证接口收到的格式统一。如果接口返回的车次字段和页面渲染字段不一致可以在success里做一层映射把train_code转成trainNo之类的。4. 避坑与排查调试查询功能时容易翻车的几个点4.1 现象开发者工具里请求成功真机预览失败原因小程序正式环境要求请求域名在后台配置白名单且必须是 HTTPS。开发者工具默认不校验真机走严格模式。解决在微信公众平台后台「开发管理」里添加 request 合法域名。如果只是本地调试可以在开发者工具「详情」里勾选「不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书」。但上线前必须配好域名否则用户端会直接报错。4.2 现象列表渲染出来但余票状态全是「无票」原因接口返回的余票字段可能是字符串0或有而代码里用 0比较字符串和数字比较会触发隐式转换但有 0是false。解决先打印res.data.list看实际字段类型。如果是字符串用item.seatCount ! 0或parseInt(item.seatCount) 0。我一般会在setData之前做一次数据清洗把余票统一转成数字。4.3 现象跳转结果页后参数丢失或乱码原因URL 拼接时没有对中文或特殊字符做编码wx.navigateTo的url长度也有限制。解决用encodeURIComponent包一层接收时用decodeURIComponent还原。如果参数很多可以只传一个 ID在结果页重新请求详情。另外注意url最大长度是 1024 字节超长会跳转失败。4.4 现象查询接口返回 403 或频繁超时原因部分公开接口有频率限制或需要特定请求头比如Referer或User-Agent。解决小程序wx.request不能自定义User-Agent但可以加header字段。如果接口对来源校验严格建议换一个稳定的数据源或者自己搭一层后端转发。不要在小程序里硬编码密钥容易被反编译。4.5 现象日期选择器在 iOS 上显示英文原因picker组件的语言跟随系统iOS 某些版本会显示英文月份。解决这是系统级行为不影响功能。如果必须统一中文可以用自定义 picker 或第三方组件库。我一般接受这个差异因为用户对日期格式的敏感度不高。5. 二次开发与改造从查询工具到可复用的数据面板这个项目最值钱的地方不是查询本身而是它把「输入 → 请求 → 渲染」这条链路跑通了。如果你想把它改成别的查询工具比如航班、汽车票、快递只需要换三样东西车站字典、接口地址、列表字段映射。我一般会先把utils/config.js里的BASE_URL抽成环境变量用wx.getAccountInfoSync判断开发版还是正式版分别指向测试和线上接口。// utils/config.js 改造版 const env wx.getAccountInfoSync().miniProgram.envVersion; const BASE_URL env develop ? https://test-api.example.com : https://api.example.com; module.exports { QUERY_TRAINS: ${BASE_URL}/train/query };这样切环境不用改代码提交审核前也不会误连测试数据。另一个改造点是加缓存。查询结果可以按fromtodate存到wx.setStorageSync下次相同条件先读缓存减少请求次数。注意缓存要设过期时间火车票余票变化快建议 5 分钟失效。const cacheKey train_${from}_${to}_${date}; const cached wx.getStorageSync(cacheKey); if (cached Date.now() - cached.time 5 * 60 * 1000) { this.setData({ trains: cached.list, loading: false }); return; } // 请求成功后写入缓存 wx.setStorageSync(cacheKey, { list: res.data.list, time: Date.now() });如果你想让列表支持下拉刷新在result.json里加enablePullDownRefresh: true然后在onPullDownRefresh里重新调用queryTrains完成后wx.stopPullDownRefresh()。这个改动很小但体验提升明显。最后说一个我踩过的坑不要直接把接口返回的整个对象塞进setData数据量大的时候会触发性能警告。只取渲染需要的字段比如trainNo、fromTime、toTime、seatCount其他字段留在内存里备用。从那以后我每次做列表渲染都强制走一遍字段裁剪希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询