夜雨聆风学习资料网

ARTICLE · 1113982

微信小程序实战:从 app.js 到上报页

微信小程序实战:从 app.js 到上报页

前端系列最后一篇,  这个微信小程序。它比 uni-app / Vue 更"原始"——没有 npm 构建(原生小程序),用 .wxml/.wxss/.js/.json 四件套。源码体量小,但藏了一个小程序新手必踩的真实结构坑,值得单独讲。

一、小程序骨架:app.js / app.json / pages

全局配置在 app.json 注册页面,app.js 管启动逻辑。pages 数组第一项同样是启动页:

// app.json{  "pages": ["pages/index/index", "pages/report/add"],  "window": { "navigationBarTitleText": "my-report" }}// app.js —— 启动时调 wx.login 拿 code,发给后端换 openIdApp({  onLaunch() {    wx.login({      success: res => {        // 发送 res.code 到后台换取 openId, sessionKey, unionId      }    })  },  globalData: { userInfo: null }})

wx.login 拿到的 code 是临时登录凭证,必须马上发给后端用 code2Session 换 openid。源码里 success 回调是空的——别忘了补上请求,否则 openid 永远拿不到(这正好接你写过的 Claw 07 微信免密登录)。

二、上报页:input 组件 + 下划线动画

pages/report/add 是一个带聚焦动画的输入框 + 提交按钮。wxml 用 bindfocus/bindblur/bindinput 绑事件,{{isFocused ? 'active' : ''}} 切换下划线高亮:

<!-- pages/report/add.wxml --><formbindsubmit="formSubmit">  <viewclass="input-container">    <textclass="input-label">用户名:</text>    <inputclass="custom-input"name="username"      bindfocus="handleFocus" bindblur="handleBlur"      bindinput="handleInput" value="{{inputValue}}" />    <viewclass="underline {{isFocused ? 'active' : ''}}"></view>  </view>  <buttonform-type="submit">提交</button></form>

提交时 formSubmit 拿表单数据,wx.request 发后端:

// pages/report/add.jsformSubmit(e) {  const formData = e.detail.value  if (!this.validate(formData)) return  wx.request({    url: 'https://your-api.com/submit',   // ← 占位地址,记得换成真实接口    method: 'POST',    data: formData,    success(res) { wx.showToast({ title: '提交成功' }) }  })},validate(data) {  if (!data.username) {    wx.showToast({ title: '用户名必填', icon: 'none' })    return false  }  return true}

三、真实结构坑:事件函数放错了位置

源码里 Page() 的选项对象是这样写的:

Page({  properties: { /* ... */ },  data: {    isFocused: false,    inputValue: '',    handleFocus() { this.setData({ isFocused: true }) },   // ❌ 写在 data 里    handleBlur()  { /* ... */ },                            // ❌ data 里不该放函数    handleInput(e) { /* ... */ }  },  methods: {    handleFocus() { /* ... */ },   // ✅ 又写了一遍    handleBlur()  { /* ... */ },    handleInput(e) { /* ... */ }  },  formSubmit(e) { /* ... */ }})

问题在这:小程序的事件处理函数(handleFocus/handleBlur/handleInput)被同时写进了 data 和 methods。而小程序规定:data 只放响应式数据(字符串/数字/数组/对象),函数必须放在 methods 或顶层。把函数塞进 data,它既不是响应式数据、又不会被当事件处理器注册——等于白写,wxml 里 bindfocus="handleFocus" 找到的是 methods 里那份。

正确写法:data 只留数据,函数全部放 methods(或顶层):

data: { isFocused: false, inputValue: '' },methods: { handleFocus() { this.setData({ isFocused: true }) }, ... }

这个坑很典型:从 Vue 转小程序的人,容易把"data 里既能放数据又能放方法"的直觉带过来,结果调试半天发现聚焦动画不生效。记住——小程序 data 是纯数据,方法去 methods。

四、和后端怎么串:免密登录闭环

这个小程序如果接你之前写的微信免密登录(Claw 07),链路是:

① 小程序 wx.login 拿 code → 发给后端 /public/wechat/get-open-id/{code} 换 openId(对应 uni-app 里的 getOpenId)。

② 前端拼 OAuth2 授权链接带上 wx_openid,跳授权服务器。

③ 后端用 openId 找到用户直接发 token(免密),跳回小程序回调页。

④ 小程序侧把 token 存 wx.setStorageSync,后续 wx.request 的 header 里带上。

注意小程序里 wx.request 默认不带 cookie、也不共享浏览器 token,所以每个请求都得手动塞 Authorization 头,没法像网页那样靠会话自动带。

五、小结

原生小程序的套路就三样:app.json 注册页面、Page() 里 data 放数据/methods 放函数、wxml 用 bind* 绑事件。最容易踩的结构坑就是"把方法写进 data"——这次的源码正好中招。把 wx.login 的 success 补上、占位接口换成真实地址、方法挪出 data,这个上报页就能跑了

相关学习资料