主题
项目介绍与 uni-app 基础(三)
本页对应 项目介绍与 uni-app 基础,共 6 段视频,约 50 分钟。
学习目标
- 能说明小程序最外层
page标签选择器及 SCSS 变量需以$开头的语法规则,并据此修正样式代码。 - 能在
pages.json中配置页面路径、页面style标题及globalStyle全局窗口配置,并验证页面配置对全局配置的覆盖效果。 - 能配置
tabBar的list(2–5 项)、页面路径与文字,并将图标资源放入static目录后验证 H5 和小程序端显示与切换。 - 能配置
subPackages分包,正确设置root与分包页面pages,避免路径重复包含root,并验证分包页面可跳转访问。 - 能排查 tabBar 图标不显示、分包路径书写错误、代码未保存或自动保存导致的常见问题。
- 能通过插件市场安装
uni-ui,直接使用倒计时、日历等扩展组件,并查阅文档调整组件参数。
知识点
一、先把两个“小坑”说清楚
为什么需要:这两点是课间答疑,但它们是后面所有配置的基础,不理解会一直糊涂。
怎么想:第一,原生小程序页面最外层那个标签是什么?我们写代码时从来没写过它,但它其实一直存在——它叫 page,相当于网页里的 body。所以你在样式里写 page { ... },用的是标签选择器,不是类选择器也不是 ID 选择器。
第二,CSS 变量。uni-app 里有一些变量是框架自己定义好的,你可以不用,也可以删掉自己重新定义;但定义时语法有要求,变量名前面要带特定前缀($),前缀后面才是你自己起的名字,叫 abc、叫 bcd 都行。变量定义好之后,在哪里使用它,那个位置最终就会变成它对应的值。
易错点:看到 page 以为是类名,写成 .page 就选不中了;自定义变量忘了写前缀,编译直接不认。
二、pages.json:页面路径与页面局部配置
为什么需要:原生小程序里,页面路径和窗口表现都写在 app.json 里;到了 uni-app,这些配置全部搬到了根目录的 pages.json,不配就访问不到页面。
怎么想:pages.json 里同样有 pages 数组,但每一项除了页面路径,还多了一个 style 字段。style 就是页面的局部配置,它对应原生小程序里每个页面目录下那个 .json 文件。也就是说,原生里“页面.json 写的东西”,现在写进 pages.json 对应页面的 style 里。
怎么做:想把标题从默认的 uni-app 改成“学习 uni-app”,就在 pages.json 里找到这个页面的 style,修改 navigationBarTitleText 的值,保存后 H5 和小程序都会变。
易错点:改完没生效,先确认你当前运行的平台是不是只有 H5——如果只开了 H5 的编译,小程序那边当然看不到变化,需要把小程序也跑起来。
三、globalStyle:全局配置与覆盖关系
为什么需要:每个页面都写一遍标题、背景色太啰嗦,需要一个全局默认值。
怎么想:globalStyle 对应原生 app.json 里的 window,原来 window 里写什么,现在就写进 globalStyle。它和页面 style 是“全局默认 + 局部覆盖”的关系:全局配了 A,某个页面配了 B,最终这个页面显示 B。
易错点:以为全局配了就一定生效,结果被页面级 style 覆盖了还不知道,先往上翻页面自己的配置。
四、tabBar:底部导航与图标踩坑
为什么需要:底部导航是小程序最常见的结构,必须会手配。
怎么想:tabBar 和 globalStyle 是平级关系,写在 pages.json 顶层。它必须有 list,list 是一个数组,每一项是一个对象,至少两项、最多五项。
怎么做:
json
"tabBar": {
"list": [
{ "pagePath": "pages/index/index", "text": "首页" },
{ "pagePath": "pages/my/my", "text": "我的" }
]
}pagePath 是页面路径,text 是显示文字,图标用 iconPath / selectedIconPath。
易错点:① 层级写错,把 tabBar 写进了 globalStyle 里面,怎么都不生效——建议把代码折叠起来看平级关系;② 只写一项就保存,直接报错;③ 图标必须放在 static 目录下。这次实测就踩到了:图标放在自建目录里,H5 能显示,小程序里却找不到图——因为不在 static 下的静态资源不会被打包进小程序目录。把图片挪进 static,按 static/xxx.png 写路径即可。
五、新建页面的两种姿势
为什么需要:tabBar 至少要两个页面,得会快速建页面。
怎么做:在目标目录上右键 → 新建页面,会弹出模板选择窗口。想用 SCSS 就选 SCSS 模板,省得自己写 lang。注意“创建同名目录”和“在 pages.json 中注册”两个勾选项:主包页面建议勾上注册,框架会自动往 pages 里补路径。
易错点:建分包页面时一定要把“注册到 pages.json”取消勾选,否则会平白多出一条主包路径,后面还要手动删。
六、subPackages:分包配置
为什么需要:小程序做分包可以优化性能,这是常规操作。
怎么想:subPackages 同样和 globalStyle 平级,是一个数组,每个分包是一个对象,必须有 root(分包根目录)和 pages(分包内页面)。分包目录习惯以 subpkg_ 开头,一眼能看出是分包。pages 里每一项是对象,除了 path 还可以有 style。
怎么做:
json
"subPackages": [
{
"root": "subpkg_task",
"pages": [
{
"path": "detail/detail",
"style": { "navigationBarTitleText": "任务详情" }
}
]
}
]易错点:root 已经写了 subpkg_task,path 里就不要再写这一层,直接从 detail/detail 开始。这次演示就因为多写了一层根目录,页面直接打不开。
七、uni-ui:扩展组件的安装与使用
为什么需要:倒计时、弹层、日历这类组件原生小程序没有,自己写成本高。uni-ui 是官方提供的组件库,角色类似 Vant,但 Vant 只适合浏览器/小程序,多端兼容性差;uni-ui 专门给 uni-app 用,打包到各家小程序和 H5 基本都没问题。
怎么做:在插件市场找到 uni-ui,登录后点“打开 HBuilderX”导入,项目里会多出 uni_modules 目录,组件就在里面。装完直接就能用,不需要像 Vue 项目那样全局注册。用法就是照文档复制粘贴再改:倒计时组件里 d 是天数、h 小时、m 分钟、s 秒;日历组件复制过来时,把没定义的变量删掉,避免报错。
易错点:不要背 API,用到哪个组件就翻文档,文档下面还有效果预览。另外页面跳转用内置的 navigator 组件,写标签名时以 u 开头会有提示,路径以 / 开头表示从根目录算起。
代码示例
示例一:pages.json —— 页面路径 / 页面配置 / 全局配置 / tabBar / 分包
json
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "学习uni-app"
}
},
{
"path": "pages/my/my",
"style": {
"navigationBarTitleText": "我的"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#007AFF",
"backgroundColor": "#FFFFFF",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/home.png",
"selectedIconPath": "static/home-active.png"
},
{
"pagePath": "pages/my/my",
"text": "我的",
"iconPath": "static/my.png",
"selectedIconPath": "static/my-active.png"
}
]
},
"subPackages": [
{
"root": "sub_pkg_task",
"pages": [
{
"path": "detail/detail",
"style": {
"navigationBarTitleText": "任务详情"
}
}
]
}
]
}要点解释与易错点:
pages数组里每项的path对应一个页面;style就是该页面的局部配置,相当于原生小程序页面目录下的页面.json,所以navigationBarTitleText写在这里只影响当前页。globalStyle相当于原生app.json的window;页面style里配了标题就会覆盖全局标题(转写稿:全局写 uni-app,页面写“学习uni-app”,最终显示“学习uni-app”)。tabBar必须与globalStyle平级,写串层级是最常见的不生效原因;list是必填项,最少 2 个、最多 5 个,只写 1 个会直接报错。iconPath的图片必须放在static目录下,否则打包不进小程序目录,H5 能显示、小程序里图标丢失。subPackages也与globalStyle平级,每个分包必须有root和pages;root直接写目录名(如sub_pkg_task),不要写./或/。- 分包
pages里的path不要再带root那一层,写成detail/detail即可(写全sub_pkg_task/detail/detail会找不到页面)。 - 新建分包页面时,不要勾选“在 pages.json 中注册”,否则会被自动加到主包
pages里;主包页面才需要那个勾选。
示例二:pages/index/index.vue —— 跳转分包页面 + 使用 uni-ui 扩展组件
vue
<template>
<view class="content">
<navigator url="/sub_pkg_task/detail/detail">跳转到分包页面</navigator>
<uni-countdown :day="1" :hour="2" :minute="30" :second="0"></uni-countdown>
<uni-calendar></uni-calendar>
</view>
</template>
<script>
export default {
data() {
return {}
}
}
</script>
<style lang="scss">
page {
background-color: #f5f5f5;
}
.content {
padding: 20rpx;
}
</style>要点解释与易错点:
navigator是内置组件,用法与原生小程序一致;url用绝对路径,/表示项目根,后面依次是分包根目录sub_pkg_task→ 页面目录detail→ 页面名detail。- 写组件名时先输入
uni-(转写稿说“以 U 开头”),HBuilderX 会给出提示,不用死记;uni-countdown、uni-calendar属于 uni-ui 扩展组件,通过插件市场安装到uni_modules目录后直接使用,不需要全局注册(这点和 Vue 项目不同)。 uni-countdown的参数含义直观:day天数、hour小时、minute分钟、second秒。- 从文档复制日历示例时,若带有
@change="xxx"之类的事件绑定,而methods里没定义对应方法,要先删掉,否则语法报错。 page是小程序最外层标签(相当于网页的body),所以page { }是标签选择器;虽然我们从不写这个标签,但它默认存在。- SCSS 变量必须 以
$开头(如$uni-color-primary),$后面才是变量名,可自定义也可删掉 uni-app 预置的。
示例三:sub_pkg_task/detail/detail.vue —— 分包内的页面
vue
<template>
<view class="detail">
<text>任务详情页(分包页面)</text>
</view>
</template>
<script>
export default {
data() {
return {}
}
}
</script>
<style lang="scss" scoped>
.detail {
padding: 30rpx;
font-size: 32rpx;
}
</style>要点解释与易错点:
- 目录结构必须是
sub_pkg_task/detail/detail.vue,与pages.json里root: "sub_pkg_task"+path: "detail/detail"严格对应,少一层或多一层都跳不过去。 - 用 HBuilderX 右键“新建页面”时选 SCSS 模板,
<style lang="scss">会自动写好,不用手敲。 - 页面标题在
pages.json该分包的pages项里通过style.navigationBarTitleText配置(如“任务详情”),不要在页面里另找.json文件——uni-app 没有页面级 json。 - 验证分包是否配置成功:从首页点
navigator能跳进来即说明成功;跳转前建议重新运行一次项目,避免热更新缓存造成“页面打不开”的假象。
常见错误
tabBar 图标在 H5 正常,打包到小程序后图标不显示 现象:H5 端三个 tab 图标都在,切到小程序端只剩文字,图标位置空白。 原因:图标文件放在了自建的静态目录(如
images/)里,小程序打包时该目录不进入构建产物,运行时找不到文件。 修法:把图片统一放到项目根目录的static/下,路径写成/static/xxx.png这种以/static开头的形式,不要自建图片目录。刚写了一个 tabBar 的 list 项,一保存就报错 现象:只写了 1 个
list元素,编辑器立刻标红,提示数量不合法。 原因:list数量必须是 2–5 个,只写 1 个属于配置非法;若开了自动保存,会在你还没补完时就触发校验。 修法:先把 2 个及以上的项一次性补齐再保存;写配置类文件时建议关掉自动保存,用标签页上的圆点/星号判断是否已保存。tabBar/subPackages写了却完全不生效 现象:配置项明明写了,编译不报错,但页面底部没有 tab、分包页面也进不去。 原因:层级写错,把它们塞进了globalStyle内部(或pages数组里),而它们应与globalStyle同级。 修法:先把pages.json折叠,确认pages、globalStyle、tabBar、subPackages四者是同级关系,再展开写内容。分包页面跳不过去,提示找不到页面 现象:
subPackages里已声明,navigator也能点,但跳转后白屏/报找不到路径。 原因:root已指定了分包根目录,pages里又重复写了一遍根目录名,路径变成subpkg_task/subpkg_task/detail/detail。 修法:pages里只写相对root的路径,如detail/detail;同时确认新建该页面时取消勾选了"在 pages.json 中注册",避免主包pages里多出一条错误路径。改了页面标题,怎么改都不生效 现象:想改导航栏标题,翻遍项目找不到该页面的
.json文件。 原因:uni-app 里页面配置不再分散在各页面的 json 中,统一写进pages.json对应页面的style字段。 修法:在pages.json找到该页面的path,给它的style加navigationBarTitleText;全局默认标题则改globalStyle,页面级配置会覆盖全局。跳转页面时试图使用 vue-router 的写法 现象:按 Vue 项目的习惯写路由跳转,在 uni-app 里拿不到路由对象/跳不过去。 原因:uni-app 与小程序的"路由"本质就是页面跳转,不存在 vue-router 那套路由实例概念。 修法:用内置
navigator组件(url以/开头表示从根目录算起)或uni.navigateTo等 API 完成跳转。写完扩展组件不显示、控制台报变量未定义 现象:从 uni-ui 文档复制日历/倒计时示例,粘贴后页面报错。 原因:示例里绑定了示例数据(如
v-model绑定的变量),本地页面并没有定义这些变量。 修法:删掉示例中未定义的绑定,或自行在data里补上同名变量;只保留保证语法正确的部分,跑通后再按需加参数。
练习
三 tab 配置:按设计稿把底部导航配成 3 个 tab(首页 / 任务 / 我的),每个 tab 都要有文字、
pagePath和static下的图标(选中态与未选中态各一张)。验收:H5 与小程序两端切换均正常,图标都显示,且至少能来回切换 3 次不报错。页面级标题覆盖全局:在
globalStyle里设置一个全局标题,再单独把某一个页面的style标题改成别的文字。验收:能说清两个页面分别显示什么标题,以及为什么。分包 + 跳转验证:新建
subpkg_task分包目录,在其中创建一个"任务详情"页面,配置到subPackages中,并在首页放一个navigator从根路径跳过去。验收:点击能进入详情页,标题正确,控制台无"找不到页面"。接入 uni-ui:通过插件市场把 uni-ui 安装进项目,分别跑通倒计时与日历两个组件。验收:项目里出现
uni_modules目录,组件渲染正常,并且没有做任何全局注册。扩展练习:用内置
swiper组件在首页做一个轮播图,并把它作为作业提交。验收:可左右滑动、有指示点,与 tabBar 配置共存不冲突。
课堂画面






原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 答疑 | 02:07 |
| 2 | uni-app配置页面路径 | 07:41 |
| 3 | uni-app配置tabBar | 10:11 |
| 4 | uni-app配置分包 | 17:44 |
| 5 | 分包bug书写问题解释 | 01:29 |
| 6 | uni-app扩展组件 | 10:52 |
小结
pages.json是 uni-app 页面配置的唯一入口,pages/globalStyle/tabBar/subPackages四者同级,层级错一行就整块失效。- 配置关系的本质是"覆盖":
globalStyle相当于原生app.json的window,页面style相当于页面自己的 json,页面级永远压过全局级。 - 页面路径的写法取决于根有没有被指定:主包写全路径,分包里只写相对
root的部分,多写一层就是坑。 - 静态资源认
static/,不认你随手起的目录名——这是 H5 能跑、小程序跑不了的最常见原因。 list2–5 项、pages至少 1 项这类是硬性校验,写配置时先补全再保存,别让自动保存替你"报错"。- 新建页面时"是否注册到
pages.json"的勾选要分场景:主包页面勾上省事,分包页面必须取消。 - uni-ui 装完即用、无需全局注册,且是官方组件库,跨端兼容性优于 vant 这类 Web 组件库;具体用法一律查文档,不背 API。
- 这类配置项属于"查得到的记忆型知识",不需要死记,但要记住它们在哪个文件的哪一层——这才是排错的抓手。