← 返回首页

第2章: 页面开发

掌握小程序页面开发基础

页面结构

小程序页面由4个文件组成,它们具有相同的路径和文件名。

文件类型 必需 作用
.js 页面逻辑
.wxml 页面结构
.wxss 页面样式
.json 页面配置
💡 提示: 页面文件必须放在 pages 目录下,并在 app.json 中注册。

创建新页面

方法1:手动创建

1. 在 pages 目录下创建文件夹,如 home 2. 在 home 文件夹下创建4个文件: - home.js - home.wxml - home.wxss - home.json 3. 在 app.json 中注册页面路径

方法2:自动创建(推荐)

// 在 app.json 中直接添加页面路径 { "pages": [ "pages/index/index", "pages/home/home" // 添加新页面 ] } // 保存后,开发者工具会自动创建对应的文件

WXML 语法

数据绑定

<!-- pages/home/home.wxml --> <view class="container"> <!-- 文本绑定 --> <text>{{message}}</text> <!-- 属性绑定 --> <image src="{{imageUrl}}" /> <!-- 条件绑定 --> <view wx:if="{{isShow}}">显示的内容</view> <!-- 列表渲染 --> <view wx:for="{{list}}" wx:key="id"> {{index}}: {{item.name}} </view> </view> // pages/home/home.js Page({ data: { message: 'Hello World', imageUrl: '/images/logo.png', isShow: true, list: [ { id: 1, name: '项目1' }, { id: 2, name: '项目2' }, { id: 3, name: '项目3' } ] } })

条件渲染

<!-- wx:if --> <view wx:if="{{score >= 90}}">优秀</view> <view wx:elif="{{score >= 60}}">及格</view> <view wx:else>不及格</view> <!-- hidden --> <view hidden="{{!isVisible}}">内容</view> // 区别: // wx:if 会完全移除/添加元素 // hidden 只是切换 display 属性

列表渲染

<!-- 基本用法 --> <view wx:for="{{array}}" wx:key="id"> {{index}}: {{item.name}} </view> <!-- 自定义变量名 --> <view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName" wx:key="id"> {{idx}}: {{itemName.name}} </view> <!-- 嵌套循环 --> <view wx:for="{{groups}}" wx:key="groupId"> <text>{{item.groupName}}</text> <view wx:for="{{item.members}}" wx:for-item="member" wx:key="memberId"> {{member.name}} </view> </view>

WXSS 样式

尺寸单位 rpx

/* rpx 是响应式像素单位 */ /* 规定:屏幕宽度 = 750rpx */ .box { width: 750rpx; /* 屏幕宽度 */ height: 200rpx; background: #07c160; } /* 在 iPhone 6 上(屏幕宽度375px): 750rpx = 375px 1rpx = 0.5px 200rpx = 100px */

样式导入

/* 导入外部样式 */ @import "../common/common.wxss"; .container { padding: 20rpx; } /* 全局样式 app.wxss */ page { background-color: #f8f8f8; font-size: 28rpx; } /* 页面样式会覆盖全局样式 */

选择器

/* 支持的选择器 */ .class { } /* 类选择器 */ #id { } /* ID选择器 */ element { } /* 元素选择器 */ element, element { } /* 并集选择器 */ ::after { } /* 伪元素 */ ::before { } /* 伪元素 */ /* 不支持的选择器 */ /* 属性选择器、后代选择器等部分支持 */

页面生命周期

生命周期函数

Page({ data: { title: '页面标题' }, // 生命周期函数 onLoad(options) { // 页面加载时触发,一个页面只调用一次 // options 为页面跳转时传递的参数 console.log('页面加载', options) // 适合:发起网络请求、初始化数据 }, onShow() { // 页面显示/切入前台时触发 console.log('页面显示') // 适合:刷新数据、开始动画 }, onReady() { // 页面初次渲染完成时触发,一个页面只调用一次 console.log('页面渲染完成') // 适合:获取节点信息、设置导航栏 }, onHide() { // 页面隐藏/切入后台时触发 console.log('页面隐藏') // 适合:停止动画、暂停音乐 }, onUnload() { // 页面卸载时触发 console.log('页面卸载') // 适合:清理定时器、取消请求 } })

页面事件处理

Page({ // 下拉刷新 onPullDownRefresh() { console.log('下拉刷新') // 刷新数据 this.loadData() // 停止下拉刷新 wx.stopPullDownRefresh() }, // 上拉触底 onReachBottom() { console.log('上拉触底') // 加载更多数据 this.loadMore() }, // 页面滚动 onPageScroll(e) { console.log('页面滚动', e.scrollTop) }, // 用户点击右上角分享 onShareAppMessage() { return { title: '分享标题', path: '/pages/index/index', imageUrl: '/images/share.jpg' } } })

事件处理

事件绑定

<!-- WXML --> <view> <!-- bind 事件绑定(冒泡) --> <button bindtap="handleTap">点击我</button> <!-- catch 事件绑定(阻止冒泡) --> <button catchtap="handleTap">点击我</button> <!-- 传递参数 --> <button bindtap="handleTap" data-id="123" data-name="test"> 传递参数 </button> </view> // JS Page({ handleTap(e) { console.log('点击事件', e) // 获取参数 const id = e.currentTarget.dataset.id const name = e.currentTarget.dataset.name console.log(id, name) // 123 test } })

常用事件类型

<!-- 点击事件 --> <view bindtap="handleTap">点击</view> <!-- 长按事件 --> <view bindlongpress="handleLongPress">长按</view> <!-- 触摸事件 --> <view bindtouchstart="handleTouchStart">触摸开始</view> <view bindtouchmove="handleTouchMove">触摸移动</view> <view bindtouchend="handleTouchEnd">触摸结束</view> <!-- 输入事件 --> <input bindinput="handleInput" /> <input bindconfirm="handleConfirm" />

数据更新

setData 方法

Page({ data: { count: 0, user: { name: '张三', age: 20 }, list: [1, 2, 3] }, // 更新简单数据 updateCount() { this.setData({ count: this.data.count + 1 }) }, // 更新对象属性 updateUser() { this.setData({ 'user.name': '李四', 'user.age': 25 }) }, // 更新数组 updateList() { this.setData({ 'list[0]': 100, // 修改第一项 'list[3]': 4 // 添加新项 }) }, // 批量更新 batchUpdate() { this.setData({ count: 10, 'user.name': '王五', list: [10, 20, 30] }, () => { // 更新完成的回调 console.log('数据更新完成') }) } })
⚠️ 注意: 不要频繁调用 setData,会影响性能。建议合并多次更新。

页面跳转

导航方式

// 1. 保留当前页面,跳转到新页面(可返回) wx.navigateTo({ url: '/pages/detail/detail?id=123', success() { console.log('跳转成功') } }) // 2. 关闭当前页面,跳转到新页面(不可返回) wx.redirectTo({ url: '/pages/home/home' }) // 3. 跳转到 tabBar 页面 wx.switchTab({ url: '/pages/index/index' }) // 4. 关闭所有页面,打开新页面 wx.reLaunch({ url: '/pages/index/index' }) // 5. 返回上一页 wx.navigateBack({ delta: 1 // 返回的页面数,默认1 })

页面间传参

// 页面A:传递参数 wx.navigateTo({ url: '/pages/detail/detail?id=123&name=test' }) // 页面B:接收参数 Page({ onLoad(options) { console.log(options.id) // 123 console.log(options.name) // test } })

完整示例:计数器页面

WXML

<view class="container"> <view class="counter"> <text class="title">计数器</text> <view class="count">{{count}}</view> <view class="buttons"> <button bindtap="decrease">-</button> <button bindtap="reset">重置</button> <button bindtap="increase">+</button> </view> </view> </view>

WXSS

.container { display: flex; justify-content: center; align-items: center; height: 100vh; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } .counter { background: white; border-radius: 20rpx; padding: 60rpx; text-align: center; box-shadow: 0 10rpx 40rpx rgba(0,0,0,0.1); } .title { font-size: 40rpx; font-weight: bold; color: rgba(255, 255, 255, 0.85); } .count { font-size: 120rpx; font-weight: bold; color: #667eea; margin: 40rpx 0; } .buttons { display: flex; gap: 20rpx; } button { flex: 1; height: 80rpx; line-height: 80rpx; font-size: 32rpx; }

JS

Page({ data: { count: 0 }, increase() { this.setData({ count: this.data.count + 1 }) }, decrease() { this.setData({ count: this.data.count - 1 }) }, reset() { this.setData({ count: 0 }) } })

本章小结

← 上一章:小程序入门 下一章:组件使用 →