鸿蒙专家 发表于 前天 13:00

鸿蒙ASCF app.json pages到tabBar配置踩坑

在鸿蒙元服务(ASCF)开发中,app.json 是每个工程最先接触的全局配置文件。页面路由、窗口样式、底部 Tab、分包结构等都由它控制。文档里有些字段写得比较简略,实际配置时容易踩坑。本文结合实践把 app.json 的完整配置项过一遍,并整理需要注意的细节。

一、pages 与 entryPagePath:页面路由表

pages 是必填配置,第一项就是默认启动页面。路径不需要写文件后缀名,系统会自动查找对应的 .hxml 文件。例如:

{
"pages": [
    "page/index/index",
    "page/API/pages/make-phone-call/make-phone-call",
    "page/API/pages/share-api/share-api"
]
}


如果不想用第一项作为首页,可以通过 entryPagePath 覆盖,但注意不能带页面参数。

需要特别留意的是 pages 数组的顺序。它不只是路由表,第一项直接决定默认启动页。如果不写 entryPagePath,删掉或重排 pages 中的第一项,首页就会跟着变。笔者第一次重排页面顺序时,就把首页搞乱了。

二、window:窗口与导航栏配置

window 控制全局导航栏和窗口样式,常见配置如下:

{
"window": {
    "navigationBarBackgroundColor": "#0A59F7",
    "navigationBarTextStyle": "white",
    "navigationBarTitleText": "我的元服务",
    "navigationStyle": "default",
    "backgroundColor": "#f5f5f5",
    "backgroundTextStyle": "dark",
    "enablePullDownRefresh": true,
    "onReachBottomDistance": 50
}
}


这里有几个注意点:

navigationBarTextStyle 在 API 12 时限制较多:custom 模式下可以设置 black/white,default 模式只能 black。API 13 及以上才都支持。

navigationStyle 设为 custom 会隐藏导航栏,但右上角的胶囊按钮仍然保留。同时页面顶部会多出状态栏高度的空白区域,需要自己处理,否则页面内容会被状态栏挡住。

onReachBottomDistance 的单位是 px 而不是 dp,在低分辨率设备上触底距离看起来会不一样。

三、tabBar:底部 Tab 栏配置

tabBar 用于配置底部导航,示例:

{
"tabBar": {
    "color": "#999999",
    "selectedColor": "#0A59F7",
    "backgroundColor": "#ffffff",
    "borderStyle": "black",
    "position": "bottom",
    "custom": false,
    "list": [
      {
      "pagePath": "page/index/index",
      "text": "首页",
      "iconPath": "image/tab/home.png",
      "selectedIconPath": "image/tab/home-active.png"
      },
      {
      "pagePath": "page/API/index",
      "text": "API",
      "iconPath": "image/tab/api.png",
      "selectedIconPath": "image/tab/api-active.png"
      }
    ]
}
}


实际踩坑记录如下:

图标限制 40kb,图片太大不会显示。一开始没有使用工具自带的图标,自己切图结果超了,排查半天。

tabBar 页面必须在主包中,不能放在分包里。文档虽然写了,但很容易忽略。笔者分包写好后发现 tabBar 页面跳转不了,折腾了很久。

颜色支持十六进制,简写(如 #fff)其实也支持,但建议写完整六位,避免不同平台解析差异。

另外,list 中的 pagePath 必须在 pages 数组中有对应路径,否则 tabBar 页面会报错跳转不了。

四、subpackages:分包配置

分包可以把页面按功能拆分,减少首屏加载体积。示例:

{
"subpackages": [
    {
      "resource": "packageMore",
      "root": "packageMore",
      "pages": [
      "more/more",
      "detail/detail"
      ]
    }
]
}


分包后的路径写法保持不变,但编译后只会保留 pages 字段,其他字段对齐。注意 tabBar 页面不能被分到子包中。

五、resolveAlias:模块路径别名

当页面层级较深时,长长的相对路径写起来很痛苦。resolveAlias 可以给模块路径起别名:

{
"resolveAlias": {
    "~/*": "/*",
    "~/index/*": "index/*",
    "@utils/*": "utils/*",
    "subBView/*": "subpackageB/view/*"
}
}


配置之后,代码里就可以这样引用:

// 不用再写 ../../../utils/test.js
const { formatDate } = require('@utils/test');


使用 resolveAlias 有两点限制:

key 和 value 都必须以 /* 结尾,少了结尾通配符会导致匹配失败。

如果多条规则同时匹配,会选取最长的规则映射,需要注意优先级。

该能力需要 ASCF Toolkit 版本不低于 1.0.4。

六、lazyCodeLoading:代码按需注入

lazyCodeLoading 可以配置自定义组件代码按需注入,目前只支持 requiredComponents:

{
"lazyCodeLoading": "requiredComponents"
}


配置后,只有页面真正用到的组件才会被加载,有助于减少首屏体积。该配置起始版本为 1.0.13,Toolkit 需要不低于 1.0.6。

七、后台运行与隐私保护

如果元服务需要在后台运行(目前仅支持后台音乐播放 audio),可以这样声明:

{
"requiredBackgroundModes": ["audio"]
}


另外,从 2.0.1 版本开始,支持 visualEffectInBackground 配置,用于切入后台时隐藏页面内容,防止敏感信息泄露:

{
"visualEffectInBackground": "hidden"
}


该字段支持 none(不处理)和 hidden(隐藏内容)两个值。金融类元服务建议开启 hidden。

八、实际项目配置示例

下面是一个实际项目中的 app.json 配置,综合了上述常用配置项:

{
"pages": [
    "page/index/index",
    "page/API/index",
    "page/API/pages/share-api/share-api",
    "page/API/pages/make-phone-call/make-phone-call",
    "page/API/pages/battery/battery",
    "page/API/pages/accelerometer/accelerometer",
    "page/API/pages/gyroscope/gyroscope"
],
"window": {
    "navigationBarBackgroundColor": "#ffffff",
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "ASCF 演示",
    "backgroundColor": "#f5f5f5",
    "backgroundTextStyle": "dark"
},
"tabBar": {
    "color": "#999999",
    "selectedColor": "#0A59F7",
    "backgroundColor": "#ffffff",
    "borderStyle": "black",
    "list": [
      {
      "pagePath": "page/index/index",
      "text": "首页",
      "iconPath": "image/tab/home.png",
      "selectedIconPath": "image/tab/home-active.png"
      },
      {
      "pagePath": "page/API/index",
      "text": "API",
      "iconPath": "image/tab/api.png",
      "selectedIconPath": "image/tab/api-active.png"
      }
    ]
},
"resolveAlias": {
    "@utils/*": "utils/*",
    "@components/*": "components/*"
}
}


九、避坑清单总结

结合上述配置,最需要记住的坑有:

pages 顺序决定默认首页,重排时务必确认 entryPagePath。

tabBar 的 pagePath 必须与 pages 对应,且 tabBar 页面必须在主包。

tabBar 图标大小不能超过 40kb,否则不显示。

navigationStyle: custom 会带来状态栏遮挡问题,需要自行适配。

resolveAlias 的 key/value 必须以 /* 结尾,多规则匹配时按最长规则生效。

visualEffectInBackground 只在 2.0.1+ 生效,低版本不报错但不生效。

app.json 的配置项不算复杂,但很多错误不会直接报错,而是表现为页面显示异常,排查起来比较费时间。建议在工程初始化时就把这些字段确认好,避免后期返工。

热心网友2 发表于 前天 19:00

Re: 鸿蒙ASCF app.json pages到tabBar配置踩坑

感谢楼主分享,这几个坑确实很典型。尤其tabBar图标大小限制和分包问题,当时我也折腾了好久。补充一个小细节:pages数组顺序影响默认首页这点,如果不小心重排了,确实容易一脸懵。另外navigationStyle设为custom后状态栏高度处理,建议用系统提供的安全区接口动态计算,避免写死。希望后面还能看到更多ASCF实战经验贴,加油!

热心网友7 发表于 前天 19:10

Re: 鸿蒙ASCF app.json pages到tabBar配置踩坑

感谢分享,这几个坑都很真实。特别是 tabBar 图标 40kb 限制和分包不能放 tabBar 页面,新手很容易中招。还有 navigationStyle custom 后状态栏空白要自己处理,这个官方文档确实没细说。收藏了,下次配 app.json 可以少走弯路。

热心网友3 发表于 前天 19:15

Re: 鸿蒙ASCF app.json pages到tabBar配置踩坑

感谢分享,这篇把 app.json 的坑基本都点到了。特别是 tabBar 页面不能放分包那个,我当初也卡了好久,明明路径没错但就是跳不过去,后来翻文档才发现是分包的限制。还有图标 40kb 的限制确实容易忽略,自己切的图稍微大点就不显示了,折腾半天还以为是路径写错。 另外补充一个自己遇到的小细节:`entryPagePath` 虽然能指定首页,但 pages 数组第一项最好还是保持和实际首页一致,不然有时候 IDE 预览或调试工具会默认打开 pages 第一项,容易误导。还有 `onReachBottomDistance` 那个 px 单位的坑,确实在真机上不同分辨率表现不一样,调的时候建议用相对值或者直接固定距离多测几台设备。 总之 app.json 虽然看着简单,但细节真的不少,楼主的整理很实用。
页: [1]
查看完整版本: 鸿蒙ASCF app.json pages到tabBar配置踩坑