微信小程序开发全流程:从注册到上线的完整指南
最近在刷小红书时,看到不少人在分享自己的微信小程序如何靠广告月入上万,甚至更多。
这种说法不能说不真实,只能说肯定不是这么简单的事情。毕竟广告收入的多少,归根结底还是取决于用户量,不可能随便做个小程序,就能吸引大量用户来看广告。
不过,完全说不可能也不太准确,毕竟人活着总得有梦想。而且其实做一个简单的小程序成本并不高,尤其得益于云开发。小程序后期没有域名、服务器等额外的软成本,所有内容都可以部署在微信平台上。如果小程序没有火,每个月基本上只需要支付20元的基础费用,这几乎就是唯一的支出。所以,如果广告收入能超过20元,那就算是赚到了。
正好最近有点空闲时间,我也挺好奇微信小程序的开发流程相比之前有什么变化,索性就研究了一下,并把整个过程记录下来,方便以后参考。于是,就有了这篇文章。
开发前准备
注册微信公众平台
首先前往 微信公众平台 并扫码登录。如果是新用户,扫码时会引导你进行网页注册。
注册所需的资料并不复杂,但需要注意微信对不同注册主体的限制。个人主体可以注册小程序,但无法使用支付等涉及资金交易的功能。这也是为什么小红书上的宣传总是强调广告收入。毕竟,除非真有富哥富姐玩真心话大冒险输了私下给你转账,否则广告收入几乎是个人主体小程序唯一的盈利方式。
注册链接:;lang=zh_CN
链接:
创建微信小程序
一个微信公众平台账号,简单来说就是一个 开发者账号,它对应着一个 AppID(小程序ID) 。
微信官方提供了 微信开发者工具,用于小程序的开发。
因此,小程序的开发过程可以概括为:
- 注册账号
- 获取AppID
- 下载并安装微信开发者工具
- 在微信开发者工具中创建项目,绑定AppID后开始开发
微信开发者工具下载地址:.html
可选:小程序备案
已经确定小程序内容(名称 / logo)的情况下,可以提前进行小程序备案
详见:小程序备案
开始开发
小程序的开发方式与 Vue 类似,但整体上经过了微信的“魔改”。通过类似 HTML 的 WXML 构建页面,类似 CSS 的 WXSS 描述样式,以及通过类似 JavaScript 的 WXJS 渲染页面。
需要注意的是,虽然 WXSS 与 CSS 基本相似,但许多 CSS3 特性并未被继承到 WXSS 中。此外,小程序的渲染方式与传统网页有所不同,因此在开发时需要特别关注页面样式在不同设备上的兼容性和展示效果。
整体说明
小程序创建后,会得到这样一个基础目录
代码语言:python代码运行次数:0运行复制your-app/
│
├── assets/ # 存放静态资源文件(如图片、字体等)
│ ├── logo.png
│ └── bg.jpg
│
├── components/ # 自定义组件
│ ├── header/ # 头部组件文件夹
│ │ ├── header.wxml # 组件的结构文件
│ │ ├── header.wxss # 组件的样式文件
│ │ ├── header.js # 组件的逻辑文件
│ │ └── header.json # 组件的配置文件
│ │
│ └── footer/ # 底部组件文件夹
│ ├── footer.wxml
│ ├── footer.wxss
│ ├── footer.js
│ └── footer.json
│
├── pages/ # 存放小程序页面
│ ├── index/ # 首页页面文件夹
│ │ ├── index.wxml # 页面结构文件(HTML-like)
│ │ ├── index.wxss # 页面样式文件(CSS-like)
│ │ ├── index.js # 页面逻辑文件(JS)
│ │ └── index.json # 页面配置文件
│ │
│ └── other/ # 其他页面
│ ├── other.wxml
│ ├── other.wxss
│ ├── other.js
│ └── other.json
│
├── utils/ # 存放工具函数等公共代码
│ ├── util.js
│ └── helper.js
│
├── app.js # 小程序的入口文件
├── app.json # 小程序全局配置文件
├── app.wxss # 小程序全局样式文件
└── project.config.json# 小程序项目配置文件(IDE用)
页面说明
小程序的每个页面或组件通常由同名的 wxml、wxss、js 和 json 四个文件构成,这些文件之间会自动关联,无需额外的引用配置。
wxml (微信标记语言,类似HTML)
- 负责页面的结构和布局,定义页面中的元素。
- 通过 WXML 来编写页面的视图结构。
<!-- wxml 文件 -->
<view class="container">
<text>{{title}}</text>
</view>
wxss(微信样式表,类似CSS)
- 负责页面的样式设置,定义页面中元素的外观、布局等。
wxss是 CSS 的一种扩展,支持大部分标准的 CSS 特性,同时增加了小程序特有的一些功能,如尺寸单位rpx(响应式像素)。
/* wxss 文件 */
.container {
width: 100%;
padding: 20px;
background-color: #f0f0f0;
}
js(JavaScript)
- 用于页面的逻辑处理,包括数据的处理、事件的绑定、页面生命周期的管理等。
- 通过
Page()或Component()定义页面的行为和生命周期方法(如onLoad、onShow等)。
// js 文件
Page({
data: {
title: 'Hello, 小程序!'
},
onLoad: function() {
console.log('页面加载');
}
});
json(配置文件)
- 用于页面的配置,比如页面的导航栏、标题、窗口背景色等。
- 页面和组件的配置也通过
json文件来指定,包括页面是否启用分享、是否使用微信的下拉刷新等。
{
"navigationBarTitleText": "首页",
"enablePullDownRefresh": true
}
组件
组件与页面类似,由同名的 wxml、wxss、js 和 json 四个文件组成。
可以简单理解为,组件就是一个“可复用的小页面”或“功能模块”。
组件的意义在于封装可复用的 UI 结构和逻辑。例如,在小程序中,每个页面可能都会包含一个相同的标题栏,如果不使用组件,就需要在每个页面单独编写一遍,而使用组件后,只需封装一个标题栏组件,并在各个页面中引用即可。这样不仅减少了冗余代码,提高了开发效率,还能在需要调整时,只修改组件代码就能同步更新所有页面,避免遗漏或重复修改。
组件的引用
在对应页面的 json 配置文件(如 index.json)中,使用 usingComponents 引入组件。例如,假设组件位于 components/my-component/my-component 目录下:
{
"usingComponents": {
"my-component": "/components/my-component/my-component"
}
}在页面的 wxml 文件中,像 HTML 标签一样使用组件:
<my-component></my-component>
生命周期
小程序根据 js 中的 Page() 或 Component() 来区分页面或组件,他们会有各自不同的生命周期
小程序的开发多数都围绕着页面的生命周期进行
页面
页面中的自定义方法如下图表格所示:
页面进行到对应节点时便会触发对应的生命周期函数,可以不进行声明,如果不进行声明则不会被触发
生命周期函数 | 触发时机 | 适用场景 |
|---|---|---|
onLoad(options) | 页面 加载 时触发(仅触发一次) | 获取页面跳转参数、初始化数据 |
onReady() | 页面 首次渲染完成 时触发(仅触发一次) | 获取 DOM 节点信息 |
onShow() | 页面 每次显示 时触发 | 页面进入前台,适合刷新数据 |
onHide() | 页面 隐藏 时触发 | 页面跳转到其他页面 |
onUnload() | 页面 卸载 时触发 | 适用于释放资源、清除定时器 |
onPullDownRefresh() | 用户 下拉刷新 时触发 | 刷新页面数据(需要在 json 里开启) |
onReachBottom() | 用户 滚动到底部 时触发 | 适用于分页加载数据 |
onShareAppMessage() | 用户点击 分享按钮 时触发 | 自定义分享内容 |
onShareTimeline() | 用户点击 分享到朋友圈 时触发 | 适用于朋友圈分享 |
onPageScroll(event) | 页面 滚动时 触发 | 监听滚动位置 |
onResize(event) | 页面 尺寸变化 时触发 | 适用于屏幕旋转等情况 |
注意:小程序的页面管理方式和浏览器的 单页应用(SPA) 类似,采用的是 堆栈管理机制,即:
- 页面不会被立即销毁,而是存储在页面栈中。
- 新页面入栈,旧页面仍然保留在内存中,不会触发
onLoad。 - 返回旧页面时,旧页面不会重新加载,但会触发
onShow。
操作 | onLoad | onShow | onHide | onUnload |
|---|---|---|---|---|
进入页面 A | ✅ 触发 | ✅ 触发 | ❌ | ❌ |
从 A 跳转到 B | ❌ | ❌ | ✅ 触发 | ❌ |
返回 A(B -> A) | ❌ | ✅ 触发 | ❌ | ❌ |
A -> B -> 关闭 B | ❌ | ✅ 触发 | ❌ | ✅(B 卸载) |
示例
代码语言:javascript代码运行次数:0运行复制Page({
/**
* 页面的初始数据
*
* 页面的初始数据是一个对象,可以包含各种属性,这些属性将用于页面渲染
* 页面的数据会在页面加载时自动传入页面的 wxml
* 通过 data 设置的数据,可以在 wxml 中进行绑定,从而在页面中渲染
* 例如下面的数据,可以直接在 wxml 中使用 {{message}} 进行展示
* data 中的数据可以在页面的 js 中通过 this.data 访问
* 通过 this.setData 方法修改 data 中的数据,将重新渲染页面
*/
data: {
message: "Hello, 小程序!",
count: 0
},
/**
* 生命周期函数 - 监听页面加载
* 只在页面首次加载时触发一次
* 可用于获取页面参数、初始化数据等
*/
onLoad(options) {
console.log("页面加载:onLoad", options);
// 可以从 options 获取页面跳转时传递的参数
if (options.id) {
console.log("页面参数 ID:", options.id);
}
},
/**
* 生命周期函数 - 监听页面初次渲染完成
* 页面结构已渲染,但未必可见
* 适合操作 DOM
*/
onReady() {
console.log("页面渲染完成:onReady");
},
/**
* 生命周期函数 - 监听页面显示
* 每次页面进入前台时触发(包括返回该页面)
*/
onShow() {
console.log("页面显示:onShow");
},
/**
* 生命周期函数 - 监听页面隐藏
* 进入后台或跳转到其他页面时触发
*/
onHide() {
console.log("页面隐藏:onHide");
},
/**
* 生命周期函数 - 监听页面卸载
* 页面被关闭/销毁时触发(如 `wx.navigateBack()` 返回)
* 适合执行清理操作,如释放定时器
*/
onUnload() {
console.log("页面卸载:onUnload");
},
/**
* 监听用户下拉动作(用于刷新页面)
* 需要在 `page.json` 里开启 `"enablePullDownRefresh": true`
*/
onPullDownRefresh() {
console.log("用户触发下拉刷新:onPullDownRefresh");
// 模拟数据刷新
setTimeout(() => {
this.setData({ message: "数据已刷新" });
wx.stopPullDownRefresh(); // 停止刷新动画
}, 1000);
},
/**
* 页面上拉触底事件(用于加载更多数据)
* 适用于分页加载数据
*/
onReachBottom() {
console.log("页面滚动到底部:onReachBottom");
this.setData({ count: this.data.count + 1 });
},
/**
* 监听用户点击右上角分享(可自定义分享内容)
* 仅 `onShareAppMessage` 适用于普通分享
*/
onShareAppMessage() {
console.log("用户点击分享:onShareAppMessage");
return {
title: "这是一个分享标题",
path: "/pages/index/index?id=123" // 可以携带参数
};
},
/**
* 监听用户点击右上角分享到朋友圈
* 仅 `onShareTimeline` 适用于分享到朋友圈
*/
onShareTimeline() {
console.log("用户分享到朋友圈:onShareTimeline");
return {
title: "分享到朋友圈的标题"
};
},
/**
* 页面滚动触发(可用于监听滚动位置)
*/
onPageScroll(event) {
console.log("页面滚动:onPageScroll", event.scrollTop);
},
/**
* 页面尺寸变化时触发(通常用于适配屏幕旋转)
*/
onResize(event) {
console.log("页面尺寸变化:onResize", event);
}
});
组件
组件的行为与 页面 类似。 通常来说 组件不会自动卸载,而是 随页面一起缓存
组件的生命周期与页面不同,具体生命周期如下:
组件进行到对应节点时便会触发对应的生命周期函数,可以不进行声明,如果不进行声明则不会被触发
生命周期 | 作用 |
|---|---|
created() | 组件实例化时触发,数据未绑定,DOM 结构未生成 |
attached() | 组件挂载到页面节点树时触发,可获取 properties |
ready() | 组件视图渲染完成,适合操作 DOM |
moved() | 组件从一个位置移动到另一个位置(较少使用) |
detached() | 组件被移除,适合清理资源(如定时器、监听事件) |
error() | 组件内部发生错误时触发 |
pageLifetimes.show() | 组件所在的页面 onShow 时触发 |
pageLifetimes.hide() | 组件所在的页面 onHide 时触发 |
pageLifetimes.resize(size) | 组件所在页面尺寸发生变化时触发 |
注意:小程序的组件的生命周期比页面更精细,具体行为取决于组件的使用方式,有以下几个点需要被注意:
- 组件不会随页面
onShow()触发,需要手动更新数据。 - 使用
wx:if可以让组件重新创建,从而刷新数据。 - 使用
hidden只是隐藏组件,不会销毁。
行为 | 页面 onShow() 触发? | 组件 attached() 触发? | 组件 detached() 触发? |
|---|---|---|---|
wx.navigateTo() | ✅ | ❌ | ❌ |
wx.navigateBack() | ✅ | ❌ | ❌ |
wx.switchTab() | ✅ | ❌ | ❌ |
wx:if 控制组件 | - | ✅(组件被重新创建) | ✅(组件被销毁) |
hidden 控制组件 | - | ❌ | ❌ |
示例
代码语言:javascript代码运行次数:0运行复制Component({
/**
* 组件的属性列表(外部传入)
*/
properties: {
title: {
type: String,
value: "默认标题"
},
count: {
type: Number,
value: 0
}
},
/**
* 组件的内部数据
*/
data: {
innerValue: "内部数据"
},
/**
* 组件的方法列表
*/
methods: {
/**
* 自定义方法 - 增加计数
*/
increment() {
this.setData({
count: this.data.count + 1
});
this.triggerEvent("countChanged", { count: this.data.count }); // 触发事件,通知父组件
},
/**
* 自定义方法 - 组件被点击
*/
handleTap() {
console.log("组件被点击");
this.triggerEvent("componentTap", { message: "组件被点击了" });
}
},
/**
* 组件的生命周期函数
*/
lifetimes: {
/**
* created:组件实例化时触发(在组件未进入页面节点树时)
*/
created() {
console.log("组件实例化:created");
},
/**
* attached:组件挂载到页面时触发(类似于页面的 onLoad)
*/
attached() {
console.log("组件挂载到页面:attached");
},
/**
* ready:组件视图渲染完成(类似于页面的 onReady)
*/
ready() {
console.log("组件视图渲染完成:ready");
},
/**
* moved:组件被移动到其他节点(很少使用)
*/
moved() {
console.log("组件被移动:moved");
},
/**
* detached:组件从页面移除时触发(类似于页面的 onUnload)
*/
detached() {
console.log("组件被销毁:detached");
},
/**
* error:组件内部发生错误时触发(如 setData 失败)
*/
error(err) {
console.error("组件发生错误:", err);
}
},
/**
* 旧版生命周期(与 lifetimes 功能类似,可兼容旧版小程序)
*/
pageLifetimes: {
/**
* 组件所在的页面显示时触发(类似于 onShow)
*/
show() {
console.log("组件所在页面显示:pageLifetimes.show");
},
/**
* 组件所在的页面隐藏时触发(类似于 onHide)
*/
hide() {
console.log("组件所在页面隐藏:pageLifetimes.hide");
},
/**
* 组件所在的页面卸载时触发(类似于 onUnload)
*/
resize(size) {
console.log("组件所在页面尺寸变化:pageLifetimes.resize", size);
}
}
});
组件的写法与页面近乎无二,通常建议将会重复在页面中出现的部分单独写成组件,这样只要在不同的页面中引用即可,页面与组件之间可以相互传递数据
事件绑定
在微信小程序中,事件绑定是页面与用户交互的核心。事件可以绑定到页面元素上,当用户与元素交互时,触发相应的 JavaScript 方法,从而实现预期的操作。
小程序提供了多种事件类型,主要如下:
事件类型 | 说明 |
|---|---|
tap | 轻触事件(点击) |
longpress / longtap | 长按(750ms 以上) |
touchstart | 手指触摸屏幕 |
touchmove | 手指在屏幕上滑动 |
touchend | 手指离开屏幕 |
touchcancel | 触摸被打断,如来电 |
scroll | 滚动事件 |
input | 输入框内容变化 |
blur | 输入框失去焦点 |
focus | 输入框获得焦点 |
change | 选项改变(picker、checkbox、radio 等) |
confirm | 输入框回车事件 |
submit | 表单提交事件 |
load | 图片加载完成 |
error | 组件加载失败 |
事件的绑定方式
微信小程序中存在多种事件绑定方式,如下:
在 wxml 中,事件绑定是以 绑定方式+事件类型="js中的函数名"
方式 | 说明 |
|---|---|
bind | 事件会冒泡 |
catch | 事件不会冒泡 |
capture-bind | 事件在捕获阶段触发(先父后子) |
capture-catch | 事件在捕获阶段触发,且不会冒泡 |
事件的冒泡
微信小程序的事件分为冒泡事件和非冒泡事件
这些事件会从子组件向父组件传递:
tap(点击)longpress(长按)touchstart/touchmove/touchend(触摸)confirm(键盘回车)
冒泡事件可以理解为,当在wxml中,一个视图容器嵌套另一个视图容器的情况下,在点击内部视图容器时,外部容器的对应事件也会被响应,因为本质上内部组件整个本身就是外部组件内部的一部分
以下文为例:


发布评论