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