Skip to content

项目介绍与 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 能跳进来即说明成功;跳转前建议重新运行一次项目,避免热更新缓存造成“页面打不开”的假象。

常见错误 ​

  1. tabBar 图标在 H5 正常,打包到小程序后图标不显示 现象:H5 端三个 tab 图标都在,切到小程序端只剩文字,图标位置空白。 原因:图标文件放在了自建的静态目录(如 images/)里,小程序打包时该目录不进入构建产物,运行时找不到文件。 修法:把图片统一放到项目根目录的 static/ 下,路径写成 /static/xxx.png 这种以 /static 开头的形式,不要自建图片目录。

  2. 刚写了一个 tabBar 的 list 项,一保存就报错 现象:只写了 1 个 list 元素,编辑器立刻标红,提示数量不合法。 原因:list 数量必须是 2–5 个,只写 1 个属于配置非法;若开了自动保存,会在你还没补完时就触发校验。 修法:先把 2 个及以上的项一次性补齐再保存;写配置类文件时建议关掉自动保存,用标签页上的圆点/星号判断是否已保存。

  3. tabBar / subPackages 写了却完全不生效 现象:配置项明明写了,编译不报错,但页面底部没有 tab、分包页面也进不去。 原因:层级写错,把它们塞进了 globalStyle 内部(或 pages 数组里),而它们应与 globalStyle 同级。 修法:先把 pages.json 折叠,确认 pages、globalStyle、tabBar、subPackages 四者是同级关系,再展开写内容。

  4. 分包页面跳不过去,提示找不到页面 现象:subPackages 里已声明,navigator 也能点,但跳转后白屏/报找不到路径。 原因:root 已指定了分包根目录,pages 里又重复写了一遍根目录名,路径变成 subpkg_task/subpkg_task/detail/detail。 修法:pages 里只写相对 root 的路径,如 detail/detail;同时确认新建该页面时取消勾选了"在 pages.json 中注册",避免主包 pages 里多出一条错误路径。

  5. 改了页面标题,怎么改都不生效 现象:想改导航栏标题,翻遍项目找不到该页面的 .json 文件。 原因:uni-app 里页面配置不再分散在各页面的 json 中,统一写进 pages.json 对应页面的 style 字段。 修法:在 pages.json 找到该页面的 path,给它的 style 加 navigationBarTitleText;全局默认标题则改 globalStyle,页面级配置会覆盖全局。

  6. 跳转页面时试图使用 vue-router 的写法 现象:按 Vue 项目的习惯写路由跳转,在 uni-app 里拿不到路由对象/跳不过去。 原因:uni-app 与小程序的"路由"本质就是页面跳转,不存在 vue-router 那套路由实例概念。 修法:用内置 navigator 组件(url 以 / 开头表示从根目录算起)或 uni.navigateTo 等 API 完成跳转。

  7. 写完扩展组件不显示、控制台报变量未定义 现象:从 uni-ui 文档复制日历/倒计时示例,粘贴后页面报错。 原因:示例里绑定了示例数据(如 v-model 绑定的变量),本地页面并没有定义这些变量。 修法:删掉示例中未定义的绑定,或自行在 data 里补上同名变量;只保留保证语法正确的部分,跑通后再按需加参数。

练习 ​

  1. 三 tab 配置:按设计稿把底部导航配成 3 个 tab(首页 / 任务 / 我的),每个 tab 都要有文字、pagePath 和 static 下的图标(选中态与未选中态各一张)。验收:H5 与小程序两端切换均正常,图标都显示,且至少能来回切换 3 次不报错。

  2. 页面级标题覆盖全局:在 globalStyle 里设置一个全局标题,再单独把某一个页面的 style 标题改成别的文字。验收:能说清两个页面分别显示什么标题,以及为什么。

  3. 分包 + 跳转验证:新建 subpkg_task 分包目录,在其中创建一个"任务详情"页面,配置到 subPackages 中,并在首页放一个 navigator 从根路径跳过去。验收:点击能进入详情页,标题正确,控制台无"找不到页面"。

  4. 接入 uni-ui:通过插件市场把 uni-ui 安装进项目,分别跑通倒计时与日历两个组件。验收:项目里出现 uni_modules 目录,组件渲染正常,并且没有做任何全局注册。

  5. 扩展练习:用内置 swiper 组件在首页做一个轮播图,并把它作为作业提交。验收:可左右滑动、有指示点,与 tabBar 配置共存不冲突。

课堂画面 ​

课堂画面 01

课堂画面 02

课堂画面 03

课堂画面 04

课堂画面 05

课堂画面 06

原视频对照 ​

#视频时长
1答疑02:07
2uni-app配置页面路径07:41
3uni-app配置tabBar10:11
4uni-app配置分包17:44
5分包bug书写问题解释01:29
6uni-app扩展组件10:52

小结 ​

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