小程序开发实战课程笔记
第一章:项目初始化与纯净环境搭建
在正式进入开发前,我们需要先创建一个干净的小程序项目环境,以便后续教学不受模板或默认配置干扰。
1.1 创建新项目
操作步骤:
- 打开 微信开发者工具。
- 点击左上角「+」号或「新建项目」按钮。
- 配置项目信息:
- 项目名称 :
demo002
- 项目目录:选择本地存储路径
- AppID:填写自己的小程序 AppID(可使用测试号)
- 项目类型:选择"小程序"
- 不使用云服务
- 不使用模板
- 项目名称 :
✅ 提示:务必勾选"不使用模板",否则会自动引入
pages/index
和pages/logs
等默认页面,增加不必要的复杂度。
示例截图描述:
- 左侧是代码编辑区;
- 中间是模拟器预览窗口;
- 右侧是调试控制台和工具面板;
- 可通过「外观」设置将模拟器移动至左侧或右侧,提升开发体验。
1.2 清理默认文件与依赖
为了构建一个"纯净"的开发环境,我们需要删除所有非必要的文件和配置项。
删除的文件/目录包括:
文件路径 | 说明 |
---|---|
/components/ |
组件目录(暂不需要) |
/miniprogram_npm/ |
npm 包缓存目录 |
/unpackage/ |
HBuilderX 相关编译产物(若存在) |
/project.config.json 中的部分字段 |
如 "libVersion" 、"cloudfunctionRoot" 等 |
修改 app.json
原始 app.json
内容可能如下:
json
{
"pages": [
"pages/index/index",
"pages/logs/logs"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "black"
},
"sitemapLocation": "sitemap.json",
"usingComponents": {}
}
我们需要做以下修改:
- 删除
"pages"
数组中的所有页面(保留空数组用于后续添加)。 - 删除
"sitemapLocation"
字段(因为我们不使用 sitemap 功能)。 - 删除
"usingComponents"
(无自定义组件时可删)。 - 若存在
"style": "v2"
或"renderer": "skyline"
,建议移除以避免兼容性问题。
✅ 修改后的 app.json
:
json
{
"pages": [],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTitleText": "小程序示例",
"navigationBarTextStyle": "black"
}
}
⚠️ 注意:JSON 文件末尾不能有多余逗号(trailing comma),否则会导致编译报错。
1.3 切换渲染模式为 webview
微信小程序支持多种渲染引擎,主要包括:
- webview 模式:传统 WebView 渲染,兼容性强,调试方便。
- Skyline 模式:新一代高性能渲染引擎,性能更好但仍在灰度测试阶段。
由于 Skyline 模式目前尚不稳定且部分 API 不兼容,我们建议初学者切换回 webview 模式。
如何切换?
打开 project.config.json
文件,查找并删除以下字段:
json
"renderer": "skyline",
"rendererMode": "webview"
或者确保没有启用 skyline
模式即可。
🔍 补充说明:如果你发现页面顶部出现黑条、字体异常、布局错乱等问题,很可能是误开启了 Skyline 模式所致。
1.4 移除 ESLint 和其他插件
某些项目模板会默认集成 ESLint、Prettier 等代码检查工具。对于新手而言,这些工具容易造成干扰。
处理方式:
- 删除根目录下的
.eslintrc.js
、.prettierrc
等配置文件; - 在微信开发者工具中关闭「ESLint 自动修复」功能(设置 → 编辑器 → 脚本校验);
这样可以避免因格式错误导致的编译中断。
1.5 创建第一个页面
接下来我们手动创建一个最简单的页面来验证环境是否正常。
步骤:
- 在
miniprogram/pages/
下新建文件夹home
; - 在
home
文件夹内创建四个文件:home.wxml
home.wxss
home.js
home.json
home.wxml
xml
<view class="container">
<text>这是我的首页</text>
</view>
home.wxss
css
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-size: 18px;
color: #333;
}
home.js
javascript
Page({
data: {},
onLoad() {
console.log("首页加载完成");
}
});
home.json
json
{}
更新 app.json
将 home
页面加入路由栈:
json
{
"pages": ["pages/home/home"]
}
保存后,开发者工具应能正确渲染出文字"这是我的首页"。
第二章:尺寸单位与样式系统详解
微信小程序的样式系统基于 CSS,并在此基础上扩展了一些特有的单位和特性。掌握这些基础知识对后续布局至关重要。
2.1 尺寸单位对比
单位 | 含义 | 是否响应式 | 使用场景 |
---|---|---|---|
px |
像素单位 | ❌ 否 | 固定大小元素 |
rpx |
responsive pixel(响应式像素) | ✅ 是 | 推荐用于移动端适配 |
rem |
根元素字体大小倍数 | ✅ 是(需配置) | 较少使用 |
% |
百分比 | ✅ 是 | 宽度、高度占比 |
rpx 的工作原理
微信小程序规定:
屏幕宽度 = 750rpx
这意味着:
- iPhone 6/7/8 屏幕宽度为 375px → 对应 750rpx
- 所以
1rpx ≈ 0.5px
- 其他设备按比例缩放
示例换算表:
设备 | 物理宽度(px) | rpx 总宽 | 1rpx ≈ ? px |
---|---|---|---|
iPhone SE (第一代) | 320px | 750rpx | ~0.427px |
iPhone 8 | 375px | 750rpx | 0.5px |
iPhone 14 Pro Max | 430px | 750rpx | ~0.572px |
实际应用建议:
- 文字大小推荐使用
rpx
,如font-size: 32rpx;
- 边距、边框、圆角等统一用
rpx
- 图片宽度可用
width: 100%;
或width: 750rpx;
实现铺满
css
/* 推荐写法 */
.title {
font-size: 36rpx;
margin: 20rpx;
padding: 30rpx;
border-radius: 16rpx;
}
2.2 样式导入与优先级
小程序支持通过 @import
导入外部样式文件。
示例:全局样式管理
- 创建
/styles/base.wxss
:
css
/* base.wxss */
.text-primary {
color: #07c160;
}
.flex-center {
display: flex;
justify-content: center;
align-items: center;
}
- 在
home.wxss
中引用:
css
@import '../../styles/base.wxss';
.container {
background-color: #f5f5f5;
}
样式优先级规则(由高到低):
- 内联样式(
style=""
) - 页面 WXSS 文件
- 组件 WXSS 文件
- App 全局 WXSS 文件
- 默认样式(小程序内置)
⚠️ 注意:WXSS 不支持 ID 选择器(如
#id
),仅支持 class、标签、属性选择器。
2.3 常见样式问题排查
问题现象 | 可能原因 | 解决方案 |
---|---|---|
样式未生效 | 选择器拼写错误、层级不对 | 检查类名、使用 .class 而非 #id |
字体模糊 | 使用了 px 而非 rpx |
改为 rpx 单位 |
布局错位 | Flex 未正确设置 | 检查 display: flex 及主轴方向 |
图片拉伸 | 未设置 mode 属性 |
设置 <image mode="aspectFit"> |
第三章:核心组件使用详解
小程序提供了丰富的内置组件,用于构建 UI 界面。本节重点介绍常用组件及其实际应用场景。
3.1 Button 组件
<button>
是最常用的交互控件之一。
基本语法:
xml
<button type="primary">主要按钮</button>
<button type="default">普通按钮</button>
<button type="warn">警告按钮</button>
属性说明:
属性 | 类型 | 说明 |
---|---|---|
type |
String | primary / default / warn |
size |
String | default / mini |
plain |
Boolean | 是否镂空 |
disabled |
Boolean | 是否禁用 |
loading |
Boolean | 显示加载动画 |
bindtap |
EventHandle | 点击事件 |
示例:带图标的按钮
xml
<button type="primary" plain bindtap="onShare" loading="{{isLoading}}">
<text class="icon-share"></text> 分享给好友
</button>
js
Page({
data: {
isLoading: false
},
onShare() {
this.setData({ isLoading: true });
wx.showModal({
title: '提示',
content: '正在分享...',
showCancel: false,
complete: () => {
this.setData({ isLoading: false });
}
});
}
});
💡 技巧:可通过
::after
伪元素添加图标,或结合 Iconfont 使用矢量图标。
3.2 Swiper 轮播图组件
<swiper>
组件常用于实现首页轮播广告图。
基本结构:
xml
<swiper
autoplay="{{true}}"
interval="3000"
duration="500"
circular="{{true}}"
indicator-dots="{{true}}"
indicator-color="#ccc"
indicator-active-color="#fff">
<block wx:for="{{banners}}" wx:key="id">
<swiper-item>
<image src="{{item.url}}" mode="aspectFill" style="width:100%;height:300rpx;" />
</swiper-item>
</block>
</swiper>
关键属性解析:
属性 | 说明 |
---|---|
autoplay |
是否自动播放 |
interval |
自动切换时间间隔(毫秒) |
duration |
滑动动画时长 |
circular |
是否可循环滑动 |
indicator-dots |
是否显示面板指示点 |
indicator-color |
指示点颜色 |
indicator-active-color |
当前激活指示点颜色 |
JS 数据准备:
javascript
Page({
data: {
banners: [
{ id: 1, url: 'https://example.com/banner1.jpg' },
{ id: 2, url: 'https://example.com/banner2.jpg' },
{ id: 3, url: 'https://example.com/banner3.jpg' }
]
}
});
自定义指示器样式(高级用法)
若需要更美观的指示器,可隐藏原生 dots 并自行绘制:
xml
<swiper bindchange="onSwiperChange" ... >
<!-- 轮播内容 -->
</swiper>
<!-- 自定义指示器 -->
<view class="indicator">
<block wx:for="{{banners.length}}" wx:key="index">
<view class="dot {{index === activeIndex ? 'active' : ''}}"></view>
</block>
</view>
js
onSwiperChange(e) {
this.setData({
activeIndex: e.detail.current
});
}
css
.indicator {
display: flex;
justify-content: center;
margin-top: -30rpx;
z-index: 999;
}
.dot {
width: 16rpx;
height: 16rpx;
background: rgba(255,255,255,0.5);
border-radius: 50%;
margin: 0 10rpx;
}
.dot.active {
background: #fff;
transform: scale(1.2);
}
3.3 View、Text、Image 等基础组件
组件 | 用途 |
---|---|
<view> |
相当于 div,块级容器 |
<text> |
文本节点,支持长按复制 |
<image> |
图片展示,支持懒加载 |
<icon> |
小图标(success, info, warn, waiting) |
image 组件注意事项:
- 必须指定宽高,否则不显示;
mode
属性决定裁剪方式,常用值:scaleToFill
: 拉伸填充aspectFit
: 保持纵横比缩放aspectFill
: 保持纵横比裁剪widthFix
: 宽度固定,高度自适应
xml
<image src="/images/logo.png" mode="widthFix" style="width:200rpx;" />
第四章:Flex 布局详解(必学!)
Flex 布局是小程序中最主流的布局方式,几乎所有的页面都依赖它来实现响应式排列。
4.1 Flex 基础概念
Flex 是 Flexible Box 的简称,即弹性盒子模型。它允许子元素在父容器中动态分配空间。
主要术语:
- 主轴(main axis):元素排列的方向
- 交叉轴(cross axis):垂直于主轴的方向
- flex container(弹性容器)
- flex item(弹性项目)
4.2 容器属性(父元素设置)
css
.container {
display: flex;
/* 主轴方向 */
flex-direction: row | row-reverse | column | column-reverse;
/* 换行 */
flex-wrap: nowrap | wrap | wrap-reverse;
/* 主轴对齐 */
justify-content: flex-start | flex-end | center | space-between | space-around;
/* 交叉轴对齐 */
align-items: stretch | flex-start | flex-end | center | baseline;
/* 多行对齐(多轴) */
align-content: stretch | flex-start | flex-end | center | space-between | space-around;
}
实战案例:九宫格布局
xml
<view class="grid-container">
<view class="grid-item" wx:for="{{9}}" wx:key="index">Item {{index + 1}}</view>
</view>
css
.grid-container {
display: flex;
flex-wrap: wrap;
padding: 20rpx;
}
.grid-item {
width: calc((750rpx - 60rpx) / 3); /* 三列,每列减去间距 */
height: 200rpx;
background: #07c160;
color: white;
text-align: center;
line-height: 200rpx;
margin: 0 10rpx 20rpx;
border-radius: 12rpx;
}
✅ 效果:每行三个格子,共三行,形成经典的"手风琴"式布局。
4.3 项目属性(子元素设置)
属性 | 作用 |
---|---|
flex-grow |
放大比例(默认0) |
flex-shrink |
缩小比例(默认1) |
flex-basis |
初始大小 |
align-self |
单独调整某个项目的对齐方式 |
示例:左右布局(左侧固定,右侧自适应)
xml
<view class="flex-layout">
<view class="left">左侧菜单</view>
<view class="right">主要内容区域</view>
</view>
css
.flex-layout {
display: flex;
height: 100vh;
}
.left {
width: 200rpx;
background: #f0f0f0;
}
.right {
flex: 1; /* 占据剩余空间 */
background: #fff;
padding: 20rpx;
}
第五章:首页综合案例开发
我们现在来动手做一个完整的首页布局,整合前面所学的知识点。
5.1 页面结构设计
首页包含以下几个模块:
- 轮播图(Swiper)
- 提示栏(Notice Bar)
- 功能入口网格(Grid)
- 新闻通知区(Flex 布局)
- 底部 TabBar(后期接入)
5.2 轮播图 + 提示栏
xml
<!-- 轮播图 -->
<swiper autoplay interval="3000" duration="500" circular indicator-dots>
<swiper-item><image src="/imgs/banner1.jpg" mode="aspectFill" style="width:100%;height:300rpx;" /></swiper-item>
<swiper-item><image src="/imgs/banner2.jpg" mode="aspectFill" style="width:100%;height:300rpx;" /></swiper-item>
</swiper>
<!-- 提示栏 -->
<view class="notice-bar">
<icon type="info" size="16" color="#ff7900" />
<text>系统维护通知:今晚23:00至凌晨2:00暂停服务。</text>
</view>
css
.notice-bar {
display: flex;
align-items: center;
background: #fdf6ec;
color: #e6a23c;
font-size: 28rpx;
padding: 16rpx 20rpx;
margin: 20rpx;
border-radius: 8rpx;
}
5.3 功能入口网格(手风琴布局)
xml
<view class="grid-section">
<view class="grid-title">常用功能</view>
<view class="grid-wrapper">
<block wx:for="{{gridItems}}" wx:key="id">
<view class="grid-cell" bindtap="onGridClick" data-id="{{item.id}}">
<image src="{{item.icon}}" mode="widthFix" />
<text>{{item.name}}</text>
</view>
</block>
</view>
</view>
js
data: {
gridItems: [
{ id: 1, name: '扫码', icon: '/icons/scan.png' },
{ id: 2, name: '付款', icon: '/icons/pay.png' },
{ id: 3, name: '收款', icon: '/icons/receive.png' },
{ id: 4, name: '卡包', icon: '/icons/card.png' },
{ id: 5, name: '出行', icon: '/icons/travel.png' },
{ id: 6, name: '健康码', icon: '/icons/health.png' },
{ id: 7, name: '发票', icon: '/icons/invoice.png' },
{ id: 8, name: '翻译', icon: '/icons/translate.png' }
]
},
onGridClick(e) {
const id = e.currentTarget.dataset.id;
wx.showToast({ title: `点击了第${id}个功能` });
}
css
.grid-section {
padding: 0 20rpx;
}
.grid-title {
font-size: 32rpx;
font-weight: bold;
margin: 30rpx 0 20rpx;
}
.grid-wrapper {
display: flex;
flex-wrap: wrap;
}
.grid-cell {
width: calc((750rpx - 60rpx) / 4);
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 40rpx;
}
.grid-cell image {
width: 80rpx;
margin-bottom: 10rpx;
}
.grid-cell text {
font-size: 26rpx;
color: #333;
}
5.4 通知区域(Flex 布局)
xml
<view class="news-section">
<view class="section-header">
<text class="title">最新通知</text>
<text class="more">查看更多 ></text>
</view>
<view class="news-list">
<view class="news-item" wx:for="{{newsList}}" wx:key="index">
<text class="dot"></text>
<text class="content">{{item.title}}</text>
<text class="time">{{item.time}}</text>
</view>
</view>
</view>
css
.news-section {
padding: 0 20rpx;
margin-top: 30rpx;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
}
.section-header .title {
font-size: 32rpx;
font-weight: bold;
}
.section-header .more {
font-size: 28rpx;
color: #999;
}
.news-item {
display: flex;
align-items: center;
margin-bottom: 16rpx;
font-size: 28rpx;
color: #555;
}
.news-item .dot {
width: 12rpx;
height: 12rpx;
background: #07c160;
border-radius: 50%;
margin-right: 16rpx;
}
.news-item .time {
margin-left: auto;
font-size: 24rpx;
color: #aaa;
}
第六章:引入图标库(Iconfont)
小程序本身提供的图标有限,我们通常使用阿里巴巴的 Iconfont 来引入更多矢量图标。
6.1 使用流程
- 访问 iconfont.cn
- 搜索所需图标(如"扫一扫"、"支付")
- 添加至项目并下载为字体文件
- 解压后上传至小程序
/fonts/
目录 - 引入字体文件
6.2 引入字体
css
/* app.wxss 或页面 wxss */
@font-face {
font-family: 'iconfont';
src: url('/fonts/iconfont.ttf') format('truetype');
}
.iconfont {
font-family: 'iconfont' !important;
font-size: 16px;
font-style: normal;
}
6.3 使用图标
xml
<text class="iconfont"></text>
获取 Unicode 编码可在 iconfont 下载包中的
demo_unicode.html
查看。
第七章:事件绑定与数据通信
7.1 常见事件类型
事件 | 触发条件 |
---|---|
bindtap |
手指触摸后抬起 |
bindinput |
输入框内容变化 |
bindchange |
状态改变(如 checkbox) |
bindscroll |
滚动触发 |
7.2 数据双向绑定(MVVM)
虽然小程序不是 Vue,但也实现了类似的数据驱动机制。
xml
<input bindinput="onInput" value="{{username}}" />
<text>你好,{{username}}!</text>
js
Page({
data: { username: '' },
onInput(e) {
this.setData({ username: e.detail.value });
}
});
第八章:页面跳转与路由管理
8.1 跳转方式
方法 | 说明 |
---|---|
wx.navigateTo |
打开新页面(可返回) |
wx.redirectTo |
替换当前页面 |
wx.switchTab |
跳转 tabBar 页面 |
wx.reLaunch |
关闭所有页面,打开目标页 |
8.2 示例:跳转详情页
js
goDetail() {
wx.navigateTo({
url: '/pages/detail/detail?id=123&name=商品A'
});
}
在目标页面获取参数:
js
Page({
onLoad(options) {
console.log(options.id); // 123
console.log(options.name); // 商品A
}
});
第九章:WXML 语法与数据渲染
WXML 类似于 Vue 的模板语法,支持数据绑定、列表渲染、条件渲染。
9.1 列表渲染 wx:for
xml
<view wx:for="{{list}}" wx:key="id">
{{index + 1}}. {{item.name}}
</view>
9.2 条件渲染 wx:if
xml
<view wx:if="{{showTips}}">显示提示</view>
<view wx:elif="{{loading}}">加载中...</view>
<view wx:else>无数据</view>
第十章:发送网络请求
调用后台接口获取数据是小程序的核心能力。
10.1 发起 GET 请求
js
wx.request({
url: 'https://api.example.com/data',
method: 'GET',
success(res) {
console.log(res.data);
this.setData({ list: res.data });
},
fail(err) {
wx.showToast({ title: '请求失败', icon: 'none' });
}
});
10.2 封装请求工具
js
// utils/request.js
function request(url, options = {}) {
return new Promise((resolve, reject) => {
wx.request({
url,
...options,
success: resolve,
fail: reject
});
});
}
module.exports = { request };
结语
覆盖了微信小程序开发的基础与核心技能。通过本篇文档的学习,你应该已经掌握了:
- 项目初始化与环境清理
- rpx 与样式系统
- Flex 布局实战
- 常用组件使用
- 页面结构搭建
- 图标引入
- 事件处理
- 页面跳转
- WXML 模板语法
- 网络请求
下一步建议:
- 动手复现本案例
- 尝试接入真实后端 API
- 学习云开发或 Taro 框架进阶