第一章:小程序入门与开发环境搭建
1.1 小程序简介与核心概念
| 概念名称 | 说明 | 注意事项 |
|---|
| 微信小程序 | 运行在微信环境内的轻量级应用,无需下载安装,即用即走。 | 不支持所有 HTML/CSS/JS 特性,需使用微信定制的框架和 API。 |
| AppID(应用ID) | 每个小程序的唯一标识,用于开发、调试和发布。 | 开发前必须注册并获取,否则无法进行真机调试和发布。 |
| 双线程架构 | 逻辑层(JS)与视图层(WXML/WXSS)分离,通过 Native 层通信。 | 逻辑层运行在 JSCore 中,无 DOM/BOM 对象,避免使用 window、document 等全局对象。 |
| WXML | 微信标记语言,用于描述页面结构,支持数据绑定、条件渲染和列表渲染。 | 类似 HTML,但标签和属性为微信定制,如 <view>、<text> 等。 |
| WXSS | 微信样式语言,基于 CSS 扩展,支持 rpx 单位和部分 CSS3 特性。 | 支持大部分 CSS 选择器,但部分高级特性受限。 |
| 逻辑层 | 处理业务逻辑、数据请求、API 调用,使用 JavaScript 编写。 | 不能直接操作视图,需通过 setData 更新页面数据。 |
| 视图层 | 负责页面渲染,由 WXML 和 WXSS 构成,运行在 WebView 中。 | 渲染性能受数据量和结构复杂度影响。 |
1.2 注册小程序账号与获取 AppID
| 概念名称 | 说明 | 注意事项 |
|---|
| 注册入口 | 访问 https://mp.weixin.qq.com 注册小程序账号。 | 需使用未注册过公众号或小程序的邮箱。 |
| 主体类型 | 个人、企业、政府、媒体等,不同类型权限和审核要求不同。 | 个人类型无法使用部分 API(如支付)。 |
| 信息填写 | 填写小程序名称、简介、头像、服务类目等基本信息。 | 名称需唯一,一旦确定不易修改。 |
| 邮箱激活 | 注册后需通过邮箱验证码激活账号。 | 确保邮箱可正常接收邮件。 |
| 主体信息认证 | 企业需对公打款或微信认证,个人需身份证实名认证。 | 认证后可获得更多权限,如发布和数据分析。 |
| AppID 获取 | 登录微信公众平台,在”开发”-“开发设置”中查看小程序 ID(AppID)。 | AppID 是开发和调试的关键,务必妥善保管。 |
1.3 安装并配置微信开发者工具
| 概念名称 | 说明 | 注意事项 |
|---|
| 开发者工具下载 | 从微信官方文档页面下载对应操作系统的版本(Windows/Mac)。 | 建议从官网下载,避免第三方渠道的安全风险。 |
| 安装流程 | 按照安装向导完成安装,无需特殊配置。 | 安装路径建议不含中文或空格。 |
| 启动与登录 | 打开工具,使用微信扫码登录。 | 需确保微信已绑定小程序管理员或开发者账号。 |
| 开发者权限 | 管理员需在公众平台添加开发者(设置-成员管理)。 | 未添加的账号无法进行项目调试。 |
| 工具界面概览 | 包含编辑器、模拟器、调试器、项目管理等面板。 | 熟悉各面板功能有助于提升开发效率。 |
| 模拟器设备选择 | 可选择不同机型、网络状态、地理位置等进行预览。 | 模拟器表现可能与真机略有差异,建议真机调试。 |
| 调试器功能 | 支持 WXML 查看、Console 日志、Network 请求监控、Storage 查看等。 | 是排查问题的重要工具,尤其用于查看 API 调用和数据流。 |
1.4 创建第一个小程序项目
| 概念名称 | 说明 | 注意事项 |
|---|
| 新建项目 | 在开发者工具中点击”新建项目”,填写项目信息。 | 需选择小程序 AppID 和本地项目存储路径。 |
| 项目配置 | 填写项目名称、选择 AppID、开发模式(小程序)、后端服务(可选)。 | 测试号可用于无 AppID 时学习,但功能受限。 |
| 项目模板选择 | 可选择”不使用云服务”的 JavaScript 基础模板。 | 初学者建议选择基础模板,便于理解结构。 |
| 项目创建完成 | 工具自动生成标准目录结构并打开首页。 | 首次加载可能需要时间,等待编译完成。 |
| 编译与预览 | 保存代码后自动编译,在模拟器中实时预览效果。 | 修改 .wxml 或 .js 文件会触发重新渲染。 |
| 真机调试 | 点击”预览”按钮,扫码在手机微信中打开调试版本。 | 真机调试可更真实地测试功能和性能。 |
1.5 项目目录结构解析
| 文件/目录名 | 说明 | 注意事项 |
|---|
project.config.json | 项目配置文件,存储项目设置(AppID、路径等)。 | 一般无需手动修改,由开发者工具管理。 |
app.js | 全局逻辑文件,定义小程序生命周期函数和全局数据。 | 必须存在,是小程序的入口文件。 |
app.json | 全局配置文件,配置页面路径、窗口样式、网络超时等。 | 不可注释,使用双引号,语法错误会导致项目无法运行。 |
app.wxss | 全局样式文件,定义全项目共用的样式。 | 可被页面样式覆盖,建议定义通用类。 |
pages/ | 页面文件夹,每个页面包含 .wxml、.wxss、.js、.json 四个文件。 | 页面路径需在 app.json 中注册才能访问。 |
utils/ | 工具类文件夹,存放公共 JavaScript 函数(如 request 封装)。 | 非必须,但推荐用于代码复用。 |
sitemap.json | 小程序页面索引配置,用于微信搜索。 | 可配置页面是否允许被索引。 |
第二章:小程序框架与页面结构
2.1 小程序框架概述(双线程模型)
| 概念名称 | 说明 | 注意事项 |
|---|
| 双线程模型 | 逻辑层(JavaScript)与视图层(WXML/WXSS)运行在不同线程。 | 提升性能和安全,避免 JS 长时间执行阻塞渲染。 |
| 逻辑层 | 运行在 JSCore 中,处理数据、逻辑和 API 调用。 | 无 DOM/BOM,不能使用 document、window 等对象。 |
| 视图层 | 运行在 WebView 中,负责页面渲染。 | 通过数据绑定接收逻辑层数据,生成 UI。 |
| Native 层 | 微信客户端原生模块,负责线程通信和系统能力调用。 | API 如摄像头、定位、支付等通过 Native 层实现。 |
| 数据通信 | 逻辑层通过 setData 将数据发送给视图层,视图层通过事件向逻辑层反馈。 | setData 是唯一更新视图的方式,频繁调用影响性能。 |
| 通信机制 | 逻辑层与视图层通过 Native 层进行序列化数据传输。 | 传输数据不能包含函数或不可序列化对象。 |
| 性能优势 | 逻辑与渲染分离,避免 JS 阻塞 UI,提升用户体验。 | 合理设计数据结构和更新频率是关键。 |
2.2 全局配置文件 app.json 详解
| 配置项 | 说明 | 注意事项 |
|---|
pages | 页面路径列表,第一个为首页。 | 路径需包含文件名(不含扩展名),如 "pages/index/index"。 |
window | 设置默认页面窗口表现(导航栏、背景色等)。 | 可被页面 .json 文件覆盖。 |
tabBar | 底部或顶部标签栏配置(list、color、selectedColor 等)。 | list 中页面必须在 pages 中注册。 |
networkTimeout | 各类网络请求的超时时间(request、connectSocket 等)。 | 单位为毫秒,建议根据业务需求设置。 |
debug | 是否开启调试模式,开启后可在开发者工具面板查看调试信息。 | 发布前建议关闭。 |
sitemapLocation | 指定 sitemap.json 文件位置。 | 默认为根目录下 sitemap.json。 |
style | 是否启用新版样式,"v2" 表示启用。 | 启用后部分组件样式可能变化。 |
subpackages | 配置分包,用于优化加载速度。 | 分包页面路径需在对应分包内。 |
2.3 页面配置文件 page.json 详解
| 配置项 | 说明 | 注意事项 |
|---|
navigationBarBackgroundColor | 导航栏背景色。 | 格式为 #RRGGBB。 |
navigationBarTextStyle | 导航栏标题颜色(仅支持 black/white)。 | - |
navigationBarTitleText | 导航栏标题文本。 | - |
backgroundColor | 窗口背景色。 | - |
backgroundTextStyle | 下拉 loading 样式(dark/light)。 | - |
enablePullDownRefresh | 是否开启下拉刷新。 | 开启后需在 js 中定义 onPullDownRefresh 函数。 |
onReachBottomDistance | 页面上拉触底事件触发时距页面底部距离(单位 px)。 | 默认 50,设为 0 表示屏幕底部触发。 |
usingComponents | 引用自定义组件的配置。 | 格式为 {"组件名": "组件路径"}。 |
2.4 全局逻辑文件 app.js 详解
| 方法名 | 语法 | 用途 | 代码示例 | 注意事项 |
|---|
onLaunch | onLaunch(Object options) | 小程序初始化完成时触发(全局只触发一次)。 | App({ onLaunch(options) { console.log('App Launch') } }) | options 为启动参数,如 scene、query 等。 |
onShow | onShow(Object options) | 小程序启动或从后台进入前台时触发。 | App({ onShow(options) { console.log('App Show') } }) | 每次切回前台都会触发。 |
onHide | onHide() | 小程序从前台进入后台时触发。 | App({ onHide() { console.log('App Hide') } }) | 无法在后台执行 JS 代码。 |
onError | onError(string error) | 小程序发生脚本错误或 API 调用失败时触发。 | App({ onError(error) { console.error('Error:', error) } }) | 可用于收集错误日志。 |
onPageNotFound | onPageNotFound(Object options) | 打开的页面不存在时触发。 | App({ onPageNotFound(res) { wx.redirectTo({url: '...' }) } }) | 可用于重定向到默认页面。 |
| 全局数据 | this.globalData = {} | 定义全局变量,供各页面通过 getApp() 访问。 | App({ globalData: { userInfo: null } }); let app = getApp(); app.globalData.userInfo | 避免存储过多数据,注意数据同步问题。 |
2.5 全局样式文件 app.wxss 详解
| 概念名称 | 说明 | 注意事项 |
|---|
| 全局样式 | 定义在整个小程序中生效的公共样式。 | 所有页面都会自动引入 app.wxss。 |
| 样式优先级 | 页面样式 > 全局样式。 | 页面 .wxss 中定义的同名样式会覆盖 app.wxss 中的样式。 |
| rpx 单位 | 响应式像素,基于屏幕宽度 750rpx 进行等比缩放。 | 设计稿宽度为 750px 时,rpx 与 px 数值相等。 |
@import | 语法:@import "common.wxss"; 在 app.wxss 中引入其他样式文件。 | 路径可为相对路径,用于模块化管理样式。 |
| 通用类定义 | 可定义 flex 布局、边距、字体等通用类。 | 如 .flex-center、.mt-20 等,提升开发效率。 |
2.6 页面文件结构(.wxml, .wxss, .js, .json)
| 文件类型 | 文件名示例 | 说明 | 注意事项 |
|---|
.json | index.json | 页面配置文件,配置窗口样式、引用组件等。 | 可为空对象,继承 app.json 配置。 |
.wxml | index.wxml | 页面结构文件,使用 WXML 语法描述 UI。 | 一个页面只能有一个根元素。 |
.wxss | index.wxss | 页面样式文件,定义该页面的私有样式。 | 样式仅在本页面生效,可覆盖全局样式。 |
.js | index.js | 页面逻辑文件,定义数据、生命周期函数和事件处理。 | 必须通过 Page() 函数注册页面,否则无法渲染。 |
Page() 方法参数:
| 参数 | 语法与说明 | 代码示例 |
|---|
data | Object,页面初始数据。 | Page({ data: { title: 'Hello' } }) |
| 生命周期函数 | onLoad、onShow、onReady、onHide、onUnload 等。 | Page({ onLoad() { console.log('Page loaded') } }) |
| 事件处理函数 | 自定义函数,响应 WXML 中绑定的事件。 | Page({ bindTap() { console.log('Tapped') } }) |
| 自定义方法 | 可定义页面内调用的私有方法。 | Page({ fetchData() { ... } }) |
setData | this.setData(Object data, Function callback),更新页面数据。 | this.setData({ title: 'New Title' }) |
第三章:WXML 模板语法
3.1 数据绑定与插值表达式
| 方法/语法 | 语法格式 | 用途 | 代码示例 | 注意事项 |
|---|
| 插值表达式 | {{ expression }} | 在 WXML 中输出数据或表达式结果。 | {{ message }} | expression 支持数据字段、简单运算、三元运算等,不支持复杂语句。 |
| 属性绑定 | attr="{{ value }}" | 将数据绑定到组件属性。 | <view class="{{ myClass }}"> | 属性值需用双引号包裹插值表达式。 |
| 路径绑定 | {{ obj.prop }} | 绑定对象或数组的深层属性。 | {{ user.profile.name }} | 路径中不能包含特殊字符或空格。 |
| 布尔属性绑定 | attr="{{ bool }} | 绑定布尔值属性,true 为真值,false 为假值。 | <checkbox checked="{{ isChecked }}"> | 若直接写 checked 不带值,视为 true。 |
| 算术运算 | {{ a + b }} | 在插值中进行加减乘除运算。 | {{ price * count }} | 运算符两侧需为数值类型,否则可能出错。 |
| 逻辑运算 | {{ flag1 && flag2 }} | 执行与、或、非等逻辑判断。 | <view wx:if="{{ a && b }}">内容</view> | 优先级与 JavaScript 一致。 |
| 字符串拼接 | {{ 'Hello ' + name }} | 拼接字符串与变量。 | {{ '用户名:' + userName }} | 推荐使用模板字符串风格,避免复杂拼接。 |
3.2 列表渲染 wx:for
| 方法/语法 | 语法格式 | 用途 | 代码示例 | 注意事项 |
|---|
wx:for | wx:for="{{ array }}" | 遍历数组生成多个组件。 | <view wx:for="{{ list }}">{{ item }}</view> | item 为默认数组元素变量名。 |
wx:for-item | wx:for-item="itemName" | 自定义数组元素变量名。 | <view wx:for="{{ list }}" wx:for-item="product">{{ product.name }}</view> | 避免与页面 data 中变量名冲突。 |
wx:for-index | wx:for-index="idx" | 自定义索引变量名。 | <view wx:for="{{ list }}" wx:for-index="i">{{ i }}: {{ item }}</view> | 默认索引名为 index。 |
wx:key | wx:key="uniqueProperty" 或 wx:key="*this" | 指定列表项的唯一标识,提升渲染性能。 | <view wx:for="{{ list }}" wx:key="id">{{ item.name }}</view> | 推荐使用唯一字段(如 id),避免使用 index。*this 用于不可变的原始类型数组。 |
| 嵌套列表渲染 | 多层 wx:for 嵌套 | 渲染二维数组或对象数组的嵌套结构。 | <view wx:for="{{ matrix }}" wx:for-item="row"><view wx:for="{{ row }}">{{ item }}</view></view> | 注意变量作用域,内层 item 覆盖外层。 |
3.3 条件渲染 wx:if / wx:elif / wx:else
| 方法/语法 | 语法格式 | 用途 | 代码示例 | 注意事项 |
|---|
wx:if | wx:if="{{ condition }}" | 当条件为真时渲染该组件。 | <view wx:if="{{ show }}">显示内容</view> | 条件为 false 时组件不会被创建,开销小。 |
wx:elif | wx:elif="{{ condition }}" | 多条件分支判断,配合 wx:if 使用。 | <view wx:if="{{ type === 1 }}">类型1</view><view wx:elif="{{ type === 2 }}">类型2</view> | 必须紧跟在 wx:if 或 wx:elif 之后。 |
wx:else | wx:else | 默认分支,当所有条件都不满足时渲染。 | <view wx:else>其他</view> | 必须紧跟在 wx:if 或 wx:elif 之后。 |
block wx:if | <block wx:if="{{ condition }}">...</block> | 控制多个组件的条件渲染,不产生实际节点。 | <block wx:if="{{ show }}"><view>A</view><view>B</view></block> | block 是逻辑包装标签,不会在视图层渲染。 |
| 与 hidden 对比 | hidden="{{ condition }}" | 隐藏组件但仍在渲染树中。 | <view hidden="{{ !show }}">内容</view> | hidden 始终渲染,适合频繁切换;wx:if 适合条件不常变的场景。 |
3.4 模板 template 的定义与使用
| 方法/语法 | 语法格式 | 用途 | 代码示例 | 注意事项 |
|---|
| 定义模板 | <template name="xxx">...</template> | 定义可复用的 WXML 结构片段。 | <template name="myTemplate"><view>{{ name }}</view></template> | name 必须唯一。 |
| 使用模板 | <template is="xxx" data="{{ ... }}"/> | 引用并渲染指定模板。 | <template is="myTemplate" data="{{ name: 'hello' }}"/> | data 传递模板所需数据。 |
| 模板作用域 | 模板内使用自身 data | 模板内部可访问传入的数据。 | 模板内直接使用 {{ greeting }} | 无法访问页面 data,必须通过 data 传参。 |
| 模板嵌套 | 模板中引用其他模板 | 构建复杂可复用结构。 | <template name="outer"><template is="inner" data="{{...}}"/></template> | 避免循环引用。 |
| 模板文件分离 | 在单独 .wxml 文件中定义模板 | 管理大型项目中的模板。 | <import src="templates.wxml"/> | 需配合 import 使用。 |
3.5 事件绑定与事件对象
| 方法/语法 | 语法格式 | 用途 | 代码示例 | 注意事项 |
|---|
| 事件绑定 | bind:eventName 或 catch:eventName | 绑定事件处理函数。bind 不阻止冒泡,catch 阻止冒泡。 | <view bind:tap="handleTap">点击</view> | 常用事件:tap、input、change、longpress 等。 |
| 事件传参 | data-param="{{ value }}" | 通过 data-* 前缀属性向事件处理函数传递参数。 | <view bind:tap="handleTap" data-id="{{ item.id }}">点击</view> | 在 event.currentTarget.dataset 中获取,如 event.currentTarget.dataset.id。 |
| 事件对象 | 参数 event | 事件触发时传递的对象,包含事件信息。 | Page({ onTap(event) { console.log(event) } }) | 包含 type、timeStamp、target、currentTarget、detail 等属性。 |
target 与 currentTarget | event.target、event.currentTarget | target 是事件源组件,currentTarget 是绑定事件的组件。 | 父视图 bindtap,点击子元素时 target 为子元素,currentTarget 为父视图。 | 区分事件源和监听者。 |
| 事件冒泡 | 事件从内层组件向外层传播 | 支持冒泡事件(如 tap)可被父组件捕获。 | <view catch:tap="handleParentTap">子元素</view> | 使用 catchtap 可阻止冒泡。 |
| 自定义事件 | this.triggerEvent('myevent', {data}) | 自定义组件中触发事件。 | this.triggerEvent('change', { value: 'new' }) | 需在组件定义中声明 events。 |
第四章:WXSS 样式与布局
4.1 WXSS 与 CSS 的异同
| 特性 | WXSS 支持情况 | 注意事项 |
|---|
| CSS 选择器 | 支持大部分 CSS 选择器(类、ID、元素、后代、子元素等)。 | 不支持伪类如 :hover,部分复杂选择器可能受限。 |
| CSS 属性 | 支持常用布局、盒模型、文本、背景等属性。 | 不支持部分 CSS3 动画和变换,如 transform、animation 支持有限。 |
| 尺寸单位 | 支持 px、rpx、%、em、rem 等。 | rpx 为微信特有,基于 750rpx 设计稿等比缩放。 |
| 样式导入 | 支持 @import "common.wxss"; | 路径为相对路径,可跨文件引用。 |
| 全局与局部样式 | app.wxss 为全局,页面 .wxss 为局部。 | 页面样式优先级高于全局样式。 |
| 样式隔离 | 页面样式默认不互相影响。 | 避免样式污染,但可通过全局文件共享。 |
| 不支持特性 | 不支持 CSS 变量(自定义属性)、部分滤镜、字体下载等。 | 需使用 JavaScript 或图片替代。 |
4.2 尺寸单位 rpx 详解
| 单位 | 说明 | 换算关系 | 注意事项 |
|---|
| rpx | responsive pixel,响应式像素。 | 屏幕宽度为 750rpx,在 iPhone6/7/8 下,1rpx = 0.5px = 1 物理像素。 | 设计稿以 750px 宽为基准,rpx 数值与 px 相等。 |
| px | 像素,与设备物理像素相关。 | 不同设备下 px 表现不同,非响应式。 | 建议使用 rpx 实现自适应。 |
| % | 百分比,相对于父元素尺寸。 | 用于宽度、高度等属性。 | 需确保父元素有明确尺寸。 |
| em | 相对于当前元素或父元素的字体大小。 | 常用于字体尺寸。 | 继承父元素 font-size。 |
| rem | 相对于根元素(<html>)的字体大小。 | 小程序中根元素字体大小固定,使用较少。 | 推荐统一使用 rpx。 |
| 自适应原理 | rpx 根据屏幕宽度动态缩放。 | 设备屏幕宽度(px)/ 750 = 1rpx 对应的 px 值。 | 高度也可用 rpx,但需注意不同设备长宽比差异。 |
4.3 Flex 布局基础
容器属性:
| 属性(容器) | 语法与说明 | 代码示例 | 注意事项 |
|---|
display | display: flex; 将元素设为 Flex 容器。 | .container { display: flex; } | 必须设置才能启用 Flex 布局。 |
flex-direction | row | column | row-reverse | column-reverse;主轴方向。 | flex-direction: column; | 默认 row(水平)。 |
justify-content | flex-start | center | flex-end | space-between | space-around;主轴对齐。 | justify-content: center; | 控制子元素在主轴上的分布。 |
align-items | flex-start | center | flex-end | stretch;交叉轴对齐。 | align-items: center; | 默认 stretch(拉伸填满)。 |
flex-wrap | nowrap | wrap;是否换行。 | flex-wrap: wrap; | 默认 nowrap(不换行)。 |
align-content | 多行时的交叉轴对齐方式。 | align-content: space-between; | 仅在 flex-wrap: wrap 且多行时有效。 |
项目属性:
| 属性(项目) | 语法与说明 | 代码示例 | 注意事项 |
|---|
order | order: <number>; 排序顺序。 | order: 2; | 数值越小越靠前,默认 0。 |
flex-grow | flex-grow: <number>; 放大比例。 | flex-grow: 1; | 占据剩余空间的比例,0 为不放大。 |
flex-shrink | flex-shrink: <number>; 缩小比例。 | flex-shrink: 1; | 空间不足时的收缩比例,0 为不收缩。 |
flex-basis | flex-basis: <size>; 初始主轴尺寸。 | flex-basis: 200rpx; | 类似 width,优先级高于 width。 |
flex | flex: grow shrink basis; 简写属性。 | flex: 1; /* 等价于 flex: 1 1 0 */ | 推荐使用 flex: 1 快速均分空间。 |
align-self | 自定义单个项目的交叉轴对齐。 | align-self: flex-end; | 覆盖 align-items 的设置。 |
4.4 常用样式属性与选择器
| 类别 | 属性/选择器 | 说明 | 示例 |
|---|
| 盒模型 | width、height | 设置元素尺寸。 | width: 200rpx; height: 100%; |
| margin、padding | 外边距和内边距。 | margin: 20rpx; padding: 10rpx 20rpx; |
| border | 边框样式、宽度、颜色。 | border: 1rpx solid #ccc; |
| box-sizing | content-box | border-box;盒模型计算方式。 | box-sizing: border-box; |
| 布局 | display | 设置元素显示方式。 | display: flex; display: none; |
| position | static | relative | fixed | absolute;定位方式。 | position: fixed; top: 0; |
| 文本 | color、font-size | 文本颜色和大小。 | color: #333; font-size: 32rpx; |
| text-align | 文本对齐方式。 | text-align: center; |
| line-height | 行高。 | line-height: 1.5; |
| white-space | 空白处理方式。 | white-space: nowrap; |
| 背景 | background-color | 背景颜色。 | background-color: #f5f5f5; |
| background-image | 背景图片。 | background-image: url('/images/bg.png'); |
| background-size | 背景图片尺寸。 | background-size: cover; |
| 选择器 | .class | 类选择器。 | .title { font-size: 36rpx; } |
| #id | ID 选择器。 | #main { background: white; } |
| element | 元素选择器。 | view { padding: 20rpx; } |
| descendant | 后代选择器。 | .container view { margin: 10rpx; } |
| child | 子元素选择器。 | .list > .item { border-top: 1rpx solid #eee; } |
4.5 全局样式与局部样式
| 概念 | 说明 | 注意事项 |
|---|
| 全局样式 | 定义在 app.wxss 中的样式,对所有页面生效。 | 所有页面自动引入,适合定义通用类、重置样式、主题变量(模拟)。 |
| 局部样式 | 定义在页面 .wxss 中的样式,仅对当前页面生效。 | 优先级高于全局样式,可覆盖全局定义。 |
| 样式优先级 | 局部样式 > 全局样式。 | 若同名样式冲突,局部样式生效。 |
| 样式复用 | 通过全局样式定义 .common-btn、.flex-center 等通用类。 | 减少重复代码,提升一致性。 |
| 样式隔离 | 页面间样式不互相影响。 | 避免一个页面的样式意外影响其他页面。 |
| 覆盖机制 | 页面 .wxss 中定义的样式会覆盖 app.wxss 中的同名样式。 | 可有意识地利用此机制定制特定页面样式。 |
第五章:页面逻辑与 JavaScript 开发
5.1 页面生命周期函数
| 生命周期函数 | 触发时机 | 代码示例 | 注意事项 |
|---|
onLoad | 页面加载时触发,一个页面只会调用一次。 | onLoad: function(options) { console.log('页面加载', options); } | options 为页面跳转时传递的参数,适合发起网络请求、初始化数据。 |
onShow | 页面显示/切入前台时触发。 | onShow: function() { console.log('页面显示'); } | 每次页面显示都会调用,适合刷新数据、检查登录状态。 |
onReady | 页面初次渲染完成时触发,只执行一次。 | onReady: function() { console.log('页面渲染完成'); } | 此时页面已准备好,可以安全地调用 SelectorQuery。 |
onHide | 页面隐藏/切入后台时触发。 | onHide: function() { console.log('页面隐藏'); } | 适合暂停定时器、音乐等耗资源操作。 |
onUnload | 页面卸载时触发,如 redirectTo 或 navigateBack。 | onUnload: function() { console.log('页面卸载'); } | 适合清除定时器、事件监听,释放内存。 |
onPullDownRefresh | 下拉刷新时触发。 | onPullDownRefresh: function() { wx.stopPullDownRefresh(); } | 需在 app.json 或页面配置中开启 enablePullDownRefresh。 |
onReachBottom | 上拉触底时触发。 | onReachBottom: function() { console.log('上拉触底'); } | 适合实现分页加载更多数据。 |
onPageScroll | 页面滚动时触发。 | onPageScroll: function(e) { console.log(e.scrollTop); } | e.scrollTop 为页面在垂直方向已滚动的距离(px)。 |
onResize | 窗口尺寸变化时触发(如横竖屏切换)。 | onResize: function(e) { console.log(e.size); } | 仅在部分设备或场景下支持。 |
5.2 组件事件处理函数
| 事件类型 | 常见事件 | 事件处理函数示例 | 注意事项 |
|---|
| 点击事件 | tap、longpress | onTap: function(event) { console.log('点击', event); } | tap 是最常用的点击事件,响应快。 |
| 表单事件 | input、change、submit | bindinput: function(e) { this.setData({ value: e.detail.value }); } | e.detail 包含组件特定信息,如输入框的 value。 |
| 滑动事件 | touchstart、touchmove、touchend | onTouchStart: function(e) { console.log(e.touches); } | 用于实现自定义手势,注意性能。 |
| 长按事件 | longpress | onLongPress: function() { wx.showModal({ title: '提示', content: '长按触发' }); } | 可替代部分右键菜单功能。 |
| 失焦/聚焦 | focus、blur | onFocus: function(e) { console.log('获得焦点'); } | 常用于输入框交互反馈。 |
| 滑块事件 | changing、change | bindchange: function(e) { console.log('滑块值:', e.detail.value); } | changing 在拖动过程中持续触发,change 在结束时触发。 |
5.3 数据更新与 setData 方法
| 用法 | 语法与说明 | 代码示例 | 注意事项 |
|---|
| 基本用法 | this.setData({ data }) 合并更新数据并触发视图层渲染。 | this.setData({ message: 'Hello World', count: 1 }); | 不可直接修改 this.data,必须用 setData。 |
| 更新嵌套数据 | 使用点表示法更新对象属性。 | this.setData({ 'user.name': 'Alice', 'list[0].status': 'done' }); | 路径中不能有特殊字符或空格。 |
| 异步回调 | setData 是异步操作,可传入回调函数。 | this.setData({ visible: true }, () => { console.log('UI已更新'); }); | 回调在视图更新后执行,适合后续操作。 |
| 性能优化 | 只更新必要字段,避免全量更新。 | // 好:this.setData({'item.price': 99}); // 避免:this.setData({ item }); | 减少数据量可提升性能。 |
| 限制 | 单次 setData 允许修改的数据大小有限(通常 1MB)。 | // 大数据分批更新 setTimeout(() => { this.setData({ part2 }); }, 0); | 避免传递过大数据,防止卡顿或报错。 |
5.4 模块化与 require 导入
| 方法 | 语法 | 用途 | 注意事项 |
|---|
| CommonJS 模块 | 使用 module.exports 和 require。 | // utils.js
module.exports = { formatDate: function() { ... } };
// page.js
const utils = require('../../utils/utils.js'); | 小程序 JavaScript 基于 CommonJS 规范。 |
| 导出数据 | module.exports = data; 或 exports.xxx = value; | module.exports = { API_URL: 'https://api.example.com', version: '1.0.0' }; | exports 是 module.exports 的引用,不要直接赋值 exports。 |
| 导出函数 | 导出工具函数或类。 | exports.formatTime = function(date) { ... }; | 便于在多个页面复用逻辑。 |
| 导入路径 | 相对路径或绝对路径(从根目录开始)。 | const api = require('/api/index.js'); | 推荐使用相对路径,避免硬编码。 |
| 缓存机制 | 模块首次加载后会被缓存,多次 require 返回同一实例。 | const a = require('./a.js'); const b = require('./a.js'); // a === b | 适合单例模式,如全局配置、日志模块。 |
5.5 工具类函数封装
| 类别 | 函数示例 | 说明 | 注意事项 |
|---|
| 日期格式化 | formatDate(date, fmt) { // 返回 '2023-08-01 12:00' } | 统一日期显示格式。 | 可使用正则替换实现。 |
| 网络请求封装 | request(url, options) { return wx.request({...}); } | 封装 wx.request,统一处理 baseUrl、header、错误。 | 添加 loading、token 自动注入等。 |
| 本地存储 | getStorageSync(key)、setStorageSync(key, data) | 封装 wx.getStorageSync,添加前缀或加密。 | 注意同步方法阻塞 UI,大数据用异步。 |
| 防抖/节流 | debounce(func, delay) { // 防止函数频繁执行 } | 用于搜索框、滚动事件等。 | 提升性能,避免重复请求。 |
| 数据验证 | isEmail(str)、isPhone(str) | 验证用户输入。 | 使用正则表达式实现。 |
| 消息提示 | showToast(title)、showModal(content) | 封装 wx.showToast,简化调用。 | 统一提示样式和默认配置。 |
第六章:常用组件详解
| 组件 | 主要属性 | 用途 | 注意事项 |
|---|
view | hover-class、hover-start-time | 基础视图容器,类似 div。 | 支持点击态效果,是布局的基本单元。 |
scroll-view | scroll-x、scroll-y、enable-back-to-top | 可滚动视图区域。 | 需明确设置宽高,否则无法滚动。scroll-into-view 可滚动到指定元素。 |
swiper | indicator-dots、autoplay、interval、vertical | 滑块视图容器,用于轮播图。 | swiper-item 必须直接子节点,内部不宜放过多内容。 |
movable-view | direction、inertia | 可移动的视图。 | 配合 movable-area 使用,实现拖拽效果。 |
cover-view | - | 覆盖在原生组件上的视图。 | 可覆盖 map、video 等原生组件,层级最高。 |
cover-image | - | 覆盖在原生组件上的图片。 | 与 cover-view 配合使用。 |
6.2 基础内容类组件(text, icon, progress 等)
| 组件 | 主要属性 | 用途 | 注意事项 |
|---|
text | selectable、space、decode | 文本组件,支持长按复制。 | space 处理空格,decode 解码 HTML 实体。 |
icon | type、size、color | 小程序内置图标。 | type 可选 success、info、warn、waiting、cancel、download、search、clear 等。 |
progress | percent、show-info、stroke-width | 进度条。 | percent 为 0-100 的数值,show-info 显示百分比文字。 |
rich-text | nodes | 渲染 HTML 片段。 | nodes 可为字符串或节点对象数组,支持部分 HTML 标签。 |
text (嵌套) | - | 支持 text 组件嵌套以实现部分文本样式不同。 | 内部 text 可单独设置样式。 |
| 组件 | 主要属性 | 用途 | 注意事项 |
|---|
button | type、size、plain、disabled、loading | 按钮组件。 | type 有 primary、default、warn;plain 为镂空样式。 |
input | placeholder、value、password、confirm-type | 输入框。 | confirm-type 可设为 search、next 等,改变回车键文字。 |
picker | mode、range、value、bindchange | 从底部弹出的选择器。 | mode 可为 selector、time、date、region(省市区)。 |
slider | min、max、step、show-value | 滑动选择器。 | show-value 在组件右侧显示当前值。 |
switch | checked、type | 开关选择器。 | type 可为 switch(默认)或 checkbox。 |
checkbox | value、checked | 多项选择器。 | 需配合 checkbox-group 使用,通过 bindchange 获取选中值。 |
radio | value、checked | 单项选择器。 | 需配合 radio-group 使用。 |
6.4 导航类组件(navigator, functional-page-navigator)
| 组件 | 主要属性 | 用途 | 注意事项 |
|---|
navigator | url、open-type、hover-class | 页面链接。 | open-type 可为 navigate(默认)、redirect、switchTab、reLaunch、navigateBack。 |
functional-page-navigator | name、version | 跳转到插件功能页,如收银台。 | name 指定功能页,如 loginAndGetUserInfo。 |
6.5 媒体类组件(image, audio, video)
| 组件 | 主要属性 | 用途 | 注意事项 |
|---|
image | src、mode、lazy-load | 图片组件。 | mode 控制裁剪缩放,如 aspectFit、widthFix;lazy-load 延迟加载。 |
audio | src、autoplay、controls、loop | 音频组件。 | 需用户触发播放(如点击按钮),自动播放受限。 |
video | src、autoplay、controls、loop、poster | 视频组件。 | poster 为封面图;全屏播放时 cover-view 可覆盖。 |
6.6 map 组件与位置服务
| 组件/API | 主要属性/参数 | 用途 | 注意事项 |
|---|
map | longitude、latitude、scale、markers、polyline、enable-scroll | 地图组件。 | 需在 app.json 中配置 permission 请求位置权限。 |
wx.getLocation | type、altitude | 获取当前位置坐标。 | type: 'gcj02' 返回国测局坐标,用于地图展示。 |
wx.openLocation | latitude、longitude、name、address | 打开内置地图显示位置。 | 可引导用户导航。 |
markers | id、latitude、longitude、title、iconPath | 地图标记点。 | iconPath 可自定义图标。 |
polyline | points、color、width、dottedLine | 地图路线。 | points 为坐标数组,用于绘制路径。 |
第七章:API 接口调用
7.1 网络请求 API(wx.request, 上传下载)
| API | 参数与说明 | 代码示例 | 注意事项 |
|---|
wx.request | 发起 HTTPS 网络请求。 | wx.request({ url: 'https://api.example.com/data', method: 'GET', data: { page: 1 }, header: { 'content-type': 'application/json' }, success: (res) => { console.log(res.data); }, fail: (err) => { console.error(err); } }); | 必须使用 HTTPS;需在 app.json 的 request 配置 domain 白名单;data 会自动序列化。 |
wx.uploadFile | 上传文件到服务器。 | wx.chooseImage({ success: (res) => { wx.uploadFile({ url: 'https://api.example.com/upload', filePath: res.tempFilePaths[0], name: 'file', success: (uploadRes) => { console.log('上传成功'); } }); } }); | filePath 通常来自 wx.chooseImage;name 为服务器接收字段名;支持 formData 传参。 |
wx.downloadFile | 下载文件资源到本地。 | wx.downloadFile({ url: 'https://example.com/file.pdf', success: (res) => { if (res.statusCode === 200) { console.log('临时路径:', res.tempFilePath); } } }); | 返回临时文件路径,可传递给 image、audio 等组件使用;过期时间由微信管理。 |
7.2 本地数据缓存 API(wx.setStorage, wx.getStorage 等)
| API | 说明 | 代码示例 | 注意事项 |
|---|
wx.setStorage | 异步存储数据。 | wx.setStorage({ key: 'userInfo', data: { name: 'Alice', age: 25 } }); | 数据会持久化,除非用户清除微信缓存。 |
wx.setStorageSync | 同步存储数据。 | try { wx.setStorageSync('token', 'abc123'); } catch (e) { } | 阻塞当前线程,大数据慎用。 |
wx.getStorage | 异步获取数据。 | wx.getStorage({ key: 'userInfo', success: (res) => { console.log(res.data); } }); | 若 key 不存在,fail 回调触发。 |
wx.getStorageSync | 同步获取数据。 | const data = wx.getStorageSync('token'); | 若 key 不存在,返回 undefined。 |
wx.removeStorage | 移除指定 key 的数据。 | wx.removeStorage({ key: 'tempData' }); | - |
wx.clearStorage | 清空所有本地数据缓存。 | wx.clearStorage(); | 慎用,影响所有数据。 |
wx.getStorageInfo | 获取当前 storage 的相关信息。 | wx.getStorageInfo({ success: (res) => { console.log(res.keys); console.log(res.limitSize); } }); | 可获取 keys、currentSize(KB)、limitSize(KB)。 |
7.3 设备信息与系统 API(wx.getSystemInfo, wx.getNetworkType 等)
| API | 说明 | 代码示例 | 注意事项 |
|---|
wx.getSystemInfo | 获取系统信息。 | wx.getSystemInfo({ success: (res) => { console.log(res.model); console.log(res.pixelRatio); console.log(res.windowWidth); console.log(res.SDKVersion); } }); | 包含设备、系统、屏幕、微信版本等信息。 |
wx.getSystemInfoSync | 同步获取系统信息。 | const info = wx.getSystemInfoSync(); console.log(info.brand); // 如 'huawei' | - |
wx.getNetworkType | 获取网络类型。 | wx.getNetworkType({ success: (res) => { console.log(res.networkType); // wifi/2g/3g/4g/unknown } }); | 可用于判断网络状态,优化资源加载。 |
wx.onNetworkStatusChange | 监听网络状态变化。 | wx.onNetworkStatusChange((res) => { console.log('网络类型:', res.networkType); console.log('是否联网:', res.isConnected); }); | 应用全局监听,适合做离线提示。 |
wx.getBatteryInfo | 获取电池信息。 | wx.getBatteryInfo({ success: (res) => { console.log('电量:', res.level); // '100%' console.log('充电中:', res.isCharging); } }); | level 为字符串,需 parseInt。 |
7.4 媒体 API(拍照、录音、图片处理)
| API | 说明 | 代码示例 | 注意事项 |
|---|
wx.chooseImage | 从相册选择或拍照。 | wx.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: (res) => { const tempFilePaths = res.tempFilePaths; // 上传或预览 } }); | tempFilePaths 为临时路径数组;需用户授权 scope.camera 和 scope.album。 |
wx.previewImage | 预览图片。 | wx.previewImage({ current: 'https://a.jpg', urls: ['https://a.jpg', 'https://b.jpg'] }); | 可滑动查看多张图。 |
wx.startRecord / wx.stopRecord | 开始/停止录音。 | wx.startRecord(); setTimeout(() => { wx.stopRecord({ success: (res) => { const tempFilePath = res.tempFilePath; } }); }, 5000); | 自动停止时长 60 秒;需授权 scope.record。 |
wx.playVoice / wx.pauseVoice / wx.stopVoice | 播放/暂停/停止音频。 | wx.playVoice({ filePath: tempFilePath }); | 同一时间只能有一个音频在播放。 |
wx.getImageInfo | 获取图片信息。 | wx.getImageInfo({ src: 'https://example.com/image.jpg', success: (res) => { console.log(res.width, res.height); } }); | 可获取图片尺寸、路径等。 |
7.5 位置 API(wx.getLocation, wx.chooseLocation)
| API | 说明 | 代码示例 | 注意事项 |
|---|
wx.getLocation | 获取当前位置。 | wx.getLocation({ type: 'gcj02', success: (res) => { console.log(res.latitude); console.log(res.longitude); } }); | 需在 app.json 中配置 permission;返回 wgs84 或 gcj02 坐标。 |
wx.chooseLocation | 打开地图选择位置。 | wx.chooseLocation({ success: (res) => { console.log(res.name); console.log(res.address); console.log(res.latitude); } }); | 依赖手机地图应用;用户主动选择。 |
wx.openLocation | 打开内置地图显示位置。 | wx.openLocation({ latitude: 39.909, longitude: 116.397, name: '北京故宫', address: '北京市东城区景山前街4号' }); | 可引导用户导航。 |
7.6 路由与页面跳转 API(wx.navigateTo, wx.redirectTo 等)
| API | 说明 | 代码示例 | 注意事项 |
|---|
wx.navigateTo | 保留当前页面,跳转到非 tabBar 页面。 | wx.navigateTo({ url: '/pages/detail/detail?id=123' }); | 最多可打开 10 个页面;可用 wx.navigateBack 返回。 |
wx.redirectTo | 关闭当前页面,跳转到非 tabBar 页面。 | wx.redirectTo({ url: '/pages/list/list' }); | 不保留当前页面,无法返回。 |
wx.reLaunch | 关闭所有页面,打开到应用内的某个页面。 | wx.reLaunch({ url: '/pages/index/index' }); | 常用于跳转首页或登录页。 |
wx.switchTab | 跳转到 tabBar 页面。 | wx.switchTab({ url: '/pages/index/index' }); | 只能跳转 tabBar 页面,会关闭所有非 tabBar 页面。 |
wx.navigateBack | 返回上一页面或多级页面。 | wx.navigateBack({ delta: 1 // 返回层数 }); | delta 默认为 1;onUnload 会触发。 |
7.7 界面交互 API(wx.showToast, wx.showModal 等)
| API | 说明 | 代码示例 | 注意事项 |
|---|
wx.showToast | 显示消息提示框。 | wx.showToast({ title: '操作成功', icon: 'success', duration: 2000 }); | icon 可为 success、error、loading、none;duration 默认 1500ms。 |
wx.showModal | 显示模态对话框。 | wx.showModal({ title: '提示', content: '确定要删除吗?', success: (res) => { if (res.confirm) { console.log('用户点击确定'); } } }); | 用于确认操作,有”确定”和”取消”按钮。 |
wx.showLoading | 显示加载提示框。 | wx.showLoading({ title: '加载中...' }); // ... wx.hideLoading(); | 必须手动调用 wx.hideLoading 隐藏。 |
wx.showActionSheet | 显示操作菜单。 | wx.showActionSheet({ itemList: ['拍照', '从相册选择'], success: (res) => { console.log('点击了第', res.tapIndex, '项'); } }); | 适合提供多个操作选项。 |
7.8 开放接口(登录、用户信息、支付等)
| API | 说明 | 代码示例 | 注意事项 |
|---|
wx.login | 获取登录凭证(code)。 | wx.login({ success: (res) => { if (res.code) { // 将 res.code 发送到开发者服务器 } } }); | code 用于换取 openid 和 session_key;有效期 5 分钟。 |
wx.getUserInfo | 获取用户信息(需用户授权)。 | wx.getUserInfo({ success: (res) => { console.log(res.userInfo); // 昵称、头像等 console.log(res.encryptedData); // 加密数据 } }); | 需用户主动触发(如点击按钮);返回信息需在服务器解密。 |
button.open-type="getUserInfo" | 推荐的用户信息获取方式。 | <button open-type="getUserInfo" bind:getuserinfo="onGetUserInfo">获取用户信息</button> | 通过 bind:getuserinfo 事件回调获取。 |
wx.requestPayment | 发起微信支付。 | wx.requestPayment({ timeStamp: '', nonceStr: '', package: '', signType: 'MD5', paySign: '', success: (res) => { console.log('支付成功'); }, fail: (err) => { console.log('支付失败'); } }); | 参数需从开发者服务器获取;需企业资质和微信支付商户号。 |
第八章:自定义组件开发
8.1 组件的创建与注册
| 步骤 | 说明 | 代码示例 | 注意事项 |
|---|
| 创建组件 | 在项目中新建目录(如 components/my-button),包含 .wxml、.wxss、.js、.json 文件。 | - | 文件名与目录名一致。 |
| 组件配置 | 在 .json 文件中声明 component: true。 | { "component": true, "usingComponents": {} } | 必须设置 component: true 才是组件。 |
| 注册组件 | 在 .js 文件中使用 Component({}) 注册。 | Component({ options: { addGlobalClass: true // 允许使用全局样式 } }) | Component 是注册组件的函数。 |
| 使用组件 | 在页面或父组件的 .json 中声明。 | { "usingComponents": { "my-button": "/components/my-button/my-button" } } | 路径为相对或绝对路径。 |
| 引用组件 | 在 .wxml 中使用。 | <my-button text="点击我" /> | 标签名与 usingComponents 中的键一致。 |
8.2 组件的 properties 属性
| 特性 | 说明 | 代码示例 | 注意事项 |
|---|
| 定义属性 | 接收外部传入的数据。 | Component({ properties: { title: { type: String, value: '默认标题' }, disabled: { type: Boolean, value: false } } }) | type 可为 String、Number、Boolean、Object、Array、null(任意类型)。 |
| 属性类型检查 | 设置 type 进行类型校验。 | 同上 | 开发者工具会报错提示。 |
| 属性默认值 | value 为默认值。 | 同上 | 外部未传值时使用。 |
| 属性观察器 | observer 监听属性变化。 | properties: { count: { type: Number, value: 0, observer: function(newVal, oldVal) { console.log('count 变化:', oldVal, '->', newVal); } } } | 在属性值改变时触发,可用于更新内部数据或执行逻辑。 |
8.3 组件的 data 与 methods
| 部分 | 说明 | 代码示例 | 注意事项 |
|---|
| data | 组件内部私有数据。 | Component({ data: { internalValue: '组件内部状态' }, methods: { updateValue: function() { this.setData({ internalValue: '新值' }); } } }) | 类似页面的 data,通过 this.setData 更新。 |
| methods | 组件内部方法。 | 同上 | 包含事件处理函数、自定义方法等。 |
| WXML 绑定 | 在 .wxml 中使用 data 和 properties。 | {{title}}、{{internalValue}} | data 和 properties 在模板中均可直接使用。 |
8.4 组件的生命周期
| 生命周期 | 触发时机 | 代码示例 | 注意事项 |
|---|
created | 组件实例化,但节点树未生成。 | Component({ lifetimes: { created: function() { console.log('组件创建'); } } }) | 不能调用 this.createSelectorQuery。 |
attached | 组件进入页面节点树。 | lifetimes: { attached: function() { console.log('组件插入页面'); // 可安全调用节点查询 this.queryNodes(); } } | 类似页面的 onReady,适合初始化操作。 |
ready | 组件布局完成。 | lifetimes: { ready: function() { console.log('组件布局完成'); } } | - |
moved | 组件被移动到节点树另一个位置。 | lifetimes: { moved: function() { console.log('组件移动'); } } | 较少使用。 |
detached | 组件被从页面节点树移除。 | lifetimes: { detached: function() { console.log('组件移除'); // 清理定时器等 } } | 类似页面的 onUnload,用于清理资源。 |
error | 组件方法抛出错误时触发。 | lifetimes: { error: function(err) { console.error('组件错误:', err); } } | - |
8.5 组件事件通信(triggerEvent)
| 方法 | 说明 | 代码示例 | 注意事项 |
|---|
| 触发事件 | 组件内部使用 this.triggerEvent 派发事件。 | methods: { onClick: function() { this.triggerEvent('myevent', { value: '来自组件的数据' }, { bubbles: false, composed: false }); } } | myevent 为事件名,detail 为传递的数据。 |
| 监听事件 | 父组件在 WXML 中绑定事件。 | <my-button bind:myevent="onMyEvent" /> | 使用 bind: 或 catch: 前缀。 |
| 事件处理函数 | 父组件定义处理函数。 | Page({ onMyEvent: function(e) { console.log(e.detail.value); // 输出 '来自组件的数据' } }) | e.detail 包含 triggerEvent 传递的数据。 |
8.6 插槽 slot 的使用
| 类型 | 说明 | 代码示例 | 注意事项 |
|---|
| 默认插槽 | 单个匿名插槽。 | 组件 WXML:<view><slot /></view> 使用:<my-component>我是插槽内容</my-component> | - |
| 具名插槽 | 多个插槽,通过 name 区分。 | 组件 WXML:<view><slot name="header" /></view><view><slot name="footer" /></view> 使用:<my-component><view slot="header">头部</view><view slot="footer">底部</view></my-component> | 父组件使用 slot 属性指定内容插入位置。 |
| 作用域插槽 | 插槽内容可访问组件内部数据(小程序不直接支持,需变通)。 | 通过 properties 传递数据,或在事件 detail 中携带。 | 小程序原生不支持,可通过事件或 properties 模拟。 |
8.7 组件间通信与 behaviors
| 特性 | 说明 | 代码示例 | 注意事项 |
|---|
| behaviors | 用于组件间代码共享,类似”混入”(mixin)。 | // my-behavior.js
module.exports = Behavior({ properties: { commonProp: String }, data: { sharedData: '共享数据' }, methods: { sharedMethod: function() { console.log('共享方法'); } } });
// 组件中引入
Component({ behaviors: [require('my-behavior')] }) | 可继承 properties、data、methods、生命周期等。 |
| 数据共享 | 多个组件复用相同逻辑。 | 同上 | 避免逻辑重复,提高可维护性。 |
| 合并规则 | properties、data、methods 会合并,同名方法后者覆盖前者。 | - | 需注意命名冲突。 |
第九章:状态管理与项目进阶
9.1 小程序状态管理方案(全局变量、自定义事件、简单状态机)
| 方案 | 实现方式 | 代码示例 | 优点 | 缺点 | 适用场景 |
|---|
| 全局变量 (App 实例) | 在 app.js 的 globalData 中定义共享数据。 | // app.js
App({ globalData: { userInfo: null, token: '' } })
// 页面中获取
const app = getApp(); console.log(app.globalData.userInfo);
// 页面中设置
app.globalData.userInfo = { name: 'Alice' }; | 简单直接,所有页面可访问。 | 数据变更无法自动通知页面;需手动 setData;易造成数据混乱。 | 小型项目,少量共享数据(如用户信息、配置)。 |
| 自定义事件 (Event Bus) | 使用第三方库或手动实现事件订阅/发布。 | // event.js
class EventBus { constructor() { this.events = {}; } on(event, callback) { /*...*/ } emit(event, data) { /*...*/ } }
export default new EventBus();
// 页面A 发布
eventBus.emit('userLogin', userInfo);
// 页面B 订阅
eventBus.on('userLogin', (user) => { this.setData({ user }); }); | 解耦组件,支持一对多通信。 | 需要额外维护事件中心;易出现内存泄漏(未解绑);调试困难。 | 中等复杂度,需要跨组件通信的场景。 |
| 简单状态机 (Redux-like) | 手动实现类似 Redux 的状态管理(Store + Action + Reducer)。 | // store.js
let state = { count: 0 };
const reducers = { INCREMENT: (state) => ({ ...state, count: state.count + 1 }), DECREMENT: (state) => ({ ...state, count: state.count - 1 }) };
export const dispatch = (action) => { state = reducers[action.type]?.(state) || state; notifySubscribers(); };
export const getState = () => state;
// 页面中使用
const unsubscribe = subscribe(() => { this.setData({ count: store.getState().count }); }); | 状态集中管理,数据流清晰,可预测。 | 需手动实现或引入第三方库。 | 中大型项目,状态较复杂。 |
| Behavior 共享 | 使用 Behavior 封装通用状态和方法。 | // behavior.js
const shareBehavior = Behavior({ data: { sharedCount: 0 }, methods: { updateSharedCount(val) { this.setData({ sharedCount: val }); } } });
export default shareBehavior;
// 组件中引入
Component({ behaviors: [shareBehavior] }) | 复用逻辑,减少重复代码。 | 状态仍分散在各组件,非全局统一管理。 | 多个组件共享相同逻辑和状态。 |
建议:优先使用 App.globalData + onShow 监听更新。复杂项目可考虑使用 mobx-miniprogram 或 redux-miniprogram-bindings 等第三方库。
9.2 使用 npm 包管理依赖
| 步骤 | 说明 | 注意事项 |
|---|
| 1. 初始化项目 | 在小程序根目录执行 npm init。 | 生成 package.json。 |
| 2. 安装依赖 | 使用 npm install 包名 --save。 | 例如:npm install lodash。 |
| 3. 构建 npm | 在微信开发者工具中,点击 工具 -> 构建 npm。 | 必须执行此步,将 npm 包构建到 miniprogram_npm 目录。 |
| 4. 配置 project.config.json | 确保 packNpmManually 或 packNpmRelationList 配置正确。 | 通常无需手动修改。 |
| 5. 引入使用 | 在 JS 文件中使用 require。 | const _ = require('lodash'); _.chunk(['a', 'b', 'c', 'd'], 2); |
| 6. 注意事项 | - 仅支持纯 JS 的 npm 包,不支持含 window、document 等浏览器 API 的包。 - 包体积会影响小程序总大小,避免引入过大包。 - 每次修改 package.json 或安装新包后,需重新构建 npm。 | 小程序运行环境是 JavaScriptCore,非完整浏览器。 |
9.3 分包加载与性能优化
| 优化方向 | 具体措施 | 说明 |
|---|
| 分包加载 | 将小程序划分为主包和多个分包。 | - 主包:核心页面,必须加载,≤ 2MB。 - 分包:非核心功能,按需加载,每个 ≤ 2MB。 - 总体积 ≤ 30MB(普通小程序)。 |
| 分包配置 (app.json) | "subPackages": [{ "root": "packageA", "pages": [...] }] | subPackages 或 subpackages;独立分包可通过 wx.preloadSubPackage 预加载。 |
| 图片优化 | - 使用 WebP 格式。 - 合理尺寸,避免大图。 - 使用 lazy-load 属性。 | 减少网络传输体积。 |
| 代码优化 | - 删除未使用代码。 - 避免在 onLoad 中执行耗时操作。 - 使用 setData 优化(只更新必要字段)。 | 提升启动速度和响应速度。 |
| WXML 优化 | - 减少节点深度和数量。 - 避免复杂 wx:for 嵌套。 | 提升渲染性能。 |
| 缓存策略 | - 合理使用 wx.setStorage 缓存数据。 - 避免频繁读写。 | 减少网络请求。 |
9.4 小程序调试技巧
| 工具/方法 | 使用方式 | 用途 |
|---|
| 微信开发者工具 | 内置调试器。 | - Console:查看日志、错误。 - Sources:断点调试 JS。 - Network:监控网络请求。 - Storage:查看本地缓存。 - WXML:查看和修改节点树。 |
| 真机调试 | 点击工具栏”真机调试”按钮。 | 在真实手机上运行,更接近用户环境,可测试摄像头、GPS 等硬件。 |
| vConsole | 在 app.js 引入并初始化。 | const vConsole = require('vconsole'); new vConsole(); |
| 远程调试 | 开启”远程调试”功能,使用 Chrome DevTools。 | 功能更强大的调试工具,支持性能分析。 |
| 性能分析 | 使用开发者工具的”性能”面板。 | 分析启动耗时、JS 执行、渲染性能等。 |
| 错误监控 | 使用 App 和 Page 的 onError 钩子。 | App({ onError: function(error) { wx.request({ url: 'https://log.example.com', data: { error } }); } }) |
9.5 安全与权限控制
| 安全领域 | 措施 | 说明 |
|---|
| HTTPS | 所有网络请求必须使用 HTTPS。 | 在 app.json 的 request 字段配置合法域名。 |
| 用户隐私 | - 明确告知用户信息用途。 - 在 app.json 的 permission 字段声明所需权限(如 scope.userLocation)。 - 使用 button.open-type 获取用户信息。 | 遵守《微信小程序平台运营规范》。 |
| 数据安全 | - 敏感数据(如 openid、session_key)严禁存储在客户端。 - 服务端接口做好鉴权和校验。 | 防止数据泄露和伪造。 |
| 代码安全 | - 避免在代码中硬编码密钥、API 地址。 - 使用 wx.request 的 header 传递 token 进行身份验证。 | - |
| 内容安全 | 调用 wx.cloud.callFunction 或 wx.request 调用内容安全接口(如文本、图片检测)。 | 防止用户发布违规内容。 |
| 支付安全 | - wx.requestPayment 的参数必须由服务端生成并签名。 - 服务端需验证支付结果。 | 防止支付欺诈。 |
第十章:发布与运营
10.1 小程序代码上传与版本管理
| 步骤 | 说明 | 注意事项 |
|---|
| 1. 代码上传 | 在开发者工具点击上传按钮,填写版本号和项目备注。 | - 版本号遵循语义化版本(如 1.0.0)。 - 上传后可在管理后台查看。 |
| 2. 版本类型 | - 开发版本:开发者上传的最新代码。 - 体验版本:指定体验者可测试的版本。 - 审核版本:提交审核中的版本。 - 线上版本:已发布上线的版本。 | 一个小程序同一时间只能有一个审核版本。 |
| 3. 版本回退 | 在管理后台可将线上版本回退到之前的任一已发布版本。 | 回退操作需谨慎,会立即生效。 |
| 4. 灰度发布 | 发布时可选择”分阶段发布”,逐步放量。 | 降低新版本风险,便于监控。 |
10.2 提交审核与发布流程
| 阶段 | 操作 | 要求/说明 |
|---|
| 1. 准备 | - 确保功能完整,无严重 Bug。 - 准备审核材料:小程序截图、服务类目、隐私政策链接等。 | 仔细阅读《微信小程序审核规范》。 |
| 2. 提交审核 | 在开发者工具上传代码后,进入微信公众平台 -> 开发管理 -> 版本管理,提交审核版本。 | 填写:版本号、测试账号(如有)、提审备注、类目与标签、服务内容说明。 |
| 3. 审核中 | 微信团队进行人工审核,通常 1-7 天。 | 可能被驳回,需根据反馈修改后重新提交。 |
| 4. 审核通过 | 收到通知,可在管理后台发布。 | 可选择立即发布或定时发布。 |
| 5. 发布上线 | 点击”发布”按钮,全量用户可见。 | 发布后无法撤销,除非回退。 |
10.3 数据分析与用户反馈
| 工具/渠道 | 用途 | 说明 |
|---|
| 小程序管理后台 - 数据分析 | - 访问分析:日活、留存、启动次数。 - 用户画像:地域、设备、年龄。 - 流量分析:来源、页面访问路径。 - 自定义分析:设置关键事件。 | 基础数据,指导运营决策。 |
| 自定义埋点 | 在关键节点调用 wx.reportAnalytics 上报事件。 | wx.reportAnalytics('buy_click', { item_id: '123', price: 99.9 }); |
| 用户反馈 | - 客服消息:通过 button.open-type="contact" 接入。 - 评价系统:引导用户在”发现”-“小程序”中评分。 - 问卷调查:内置反馈表单。 | 直接获取用户意见。 |
| 监控平台 | 集成 Sentry、Bugly 等第三方监控。 | 实时监控错误、性能、崩溃。 |
10.4 小程序运营基础
| 运营方向 | 策略与方法 | 说明 |
|---|
| 用户获取 | - 社交裂变:拼团、砍价、分享有礼。 - 公众号关联:文章嵌入、菜单跳转。 - 线下场景:扫码点餐、门店导航。 - 广告投放:小程序广告、朋友圈广告。 | 利用微信社交关系链。 |
| 用户留存 | - 消息触达:模板消息(需用户触发)、订阅消息(需授权)。 - 会员体系:积分、等级、优惠券。 - 内容更新:定期推出新功能、活动。 | 提高用户活跃度和粘性。 |
| 转化提升 | - 优化用户体验:简化流程,提升加载速度。 - A/B 测试:对比不同 UI 或策略效果。 - 数据分析驱动:基于数据优化功能和营销。 | 关注核心转化率(如购买率)。 |
| 品牌建设 | - 统一视觉设计:符合品牌调性。 - 优质内容:提供有价值的信息或服务。 - 口碑传播:鼓励用户分享和好评。 | 建立长期用户信任。 |
| 持续迭代 | - 建立敏捷开发流程。 - 收集反馈,快速响应。 - 定期发布新版本。 | 保持小程序活力和竞争力。 |