Appearance
pages.json 页面路由
pages.json 文件用来对 qinjs 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生 tabbar 等。在 qinjs 中也支持 pages.json 本地调试。
它类似微信小程序中 app.json 的页面管理部分。注意定位权限申请等原属于 app.json 的内容,在 qinjs 中是在 manifest 中配置。
配置项列表
| 属性 | 类型 | 必填 | 描述 | 平台兼容 |
|---|---|---|---|---|
| extends | Object | 否 | 集成 pages.json 所有属性 | |
| compilePages | Object | 否 | 单独编译 pages 文件夹中的某一个文件 | |
| compileSubPackages | Object | 否 | 单独编译 subPackages 文件夹中的某一个文件 | |
| globalStyle | Object | 否 | 设置默认页面的窗口表现 | |
| pages | Object Array | 是 | 设置页面路径及窗口表现 | |
| easycom | Object | 否 | 组件自动引入规则 | |
| tabBar | Object | 否 | 设置底部 tab 的表现 | |
| condition | Object | 否 | 启动模式配置 | |
| subPackages | Object Array | 否 | 分包加载配置 | H5 不支持 |
| preloadRule | Object | 否 | 分包预下载规则 | 微信小程序 |
| workers | String | 否 | Worker 代码放置的目录 | 微信小程序 |
| leftWindow | Object | 否 | 大屏左侧窗口 | H5 |
| topWindow | Object | 否 | 大屏顶部窗口 | H5 |
| rightWindow | Object | 否 | 大屏右侧窗口 | H5 |
| entryPagePath | String | 否 | 默认启动首页 | 微信小程序 |
以下是一个包含了所有配置选项的 pages.json :
json
{
"pages": [{
"path": "pages/component/index",
"style": {
"navigationBarTitleText": "组件"
}
}, {
"path": "pages/API/index",
"style": {
"navigationBarTitleText": "接口"
}
}, {
"path": "pages/component/view/index",
"style": {
"navigationBarTitleText": "view"
}
}],
"condition": { //模式配置,仅开发期间生效
"current": 0, //当前激活的模式(list 的索引项)
"list": [{
"name": "test", //模式名称
"path": "pages/component/view/index" //启动页面,必选
}]
},
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "演示",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"usingComponents":{
"collapse-tree-item":"/components/collapse-tree-item"
},
"renderingMode": "seperated", // 仅微信小程序,webrtc 无法正常时尝试强制关闭同层渲染
"pageOrientation": "portrait", //横屏配置,全局屏幕旋转设置(仅 APP/微信/QQ小程序),支持 auto / portrait / landscape
"rpxCalcMaxDeviceWidth": 960,
"rpxCalcBaseDeviceWidth": 375,
"rpxCalcIncludeWidth": 750
},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"height": "50px",
"fontSize": "10px",
"iconWidth": "24px",
"spacing": "3px",
"iconfontSrc":"static/iconfont.ttf", // app tabbar 字体.ttf文件路径 app 3.4.4+
"list": [{
"pagePath": "pages/component/index",
"iconPath": "static/image/icon_component.png",
"selectedIconPath": "static/image/icon_component_HL.png",
"text": "组件",
"iconfont": { // 优先级高于 iconPath,该属性依赖 tabbar 根节点的 iconfontSrc
"text": "\ue102",
"selectedText": "\ue103",
"fontSize": "17px",
"color": "#000000",
"selectedColor": "#0000ff"
}
}, {
"pagePath": "pages/API/index",
"iconPath": "static/image/icon_API.png",
"selectedIconPath": "static/image/icon_API_HL.png",
"text": "接口"
}],
"midButton": {
"width": "80px",
"height": "50px",
"text": "文字",
"iconPath": "static/image/midButton_iconPath.png",
"iconWidth": "24px",
"backgroundImage": "static/image/midButton_backgroundImage.png"
}
},
"easycom": {
"autoscan": true, //是否自动扫描组件
"custom": {//自定义扫描规则
"^uni-(.*)": "@/components/uni-$1.vue"
}
},
"topWindow": {
"path": "responsive/top-window.vue",
"style": {
"height": "44px"
}
},
"leftWindow": {
"path": "responsive/left-window.vue",
"style": {
"width": "300px"
}
},
"rightWindow": {
"path": "responsive/right-window.vue",
"style": {
"width": "300px"
},
"matchMedia": {
"minWidth": 768
}
}
}{
"pages": [{
"path": "pages/component/index",
"style": {
"navigationBarTitleText": "组件"
}
}, {
"path": "pages/API/index",
"style": {
"navigationBarTitleText": "接口"
}
}, {
"path": "pages/component/view/index",
"style": {
"navigationBarTitleText": "view"
}
}],
"condition": { //模式配置,仅开发期间生效
"current": 0, //当前激活的模式(list 的索引项)
"list": [{
"name": "test", //模式名称
"path": "pages/component/view/index" //启动页面,必选
}]
},
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "演示",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"usingComponents":{
"collapse-tree-item":"/components/collapse-tree-item"
},
"renderingMode": "seperated", // 仅微信小程序,webrtc 无法正常时尝试强制关闭同层渲染
"pageOrientation": "portrait", //横屏配置,全局屏幕旋转设置(仅 APP/微信/QQ小程序),支持 auto / portrait / landscape
"rpxCalcMaxDeviceWidth": 960,
"rpxCalcBaseDeviceWidth": 375,
"rpxCalcIncludeWidth": 750
},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"height": "50px",
"fontSize": "10px",
"iconWidth": "24px",
"spacing": "3px",
"iconfontSrc":"static/iconfont.ttf", // app tabbar 字体.ttf文件路径 app 3.4.4+
"list": [{
"pagePath": "pages/component/index",
"iconPath": "static/image/icon_component.png",
"selectedIconPath": "static/image/icon_component_HL.png",
"text": "组件",
"iconfont": { // 优先级高于 iconPath,该属性依赖 tabbar 根节点的 iconfontSrc
"text": "\ue102",
"selectedText": "\ue103",
"fontSize": "17px",
"color": "#000000",
"selectedColor": "#0000ff"
}
}, {
"pagePath": "pages/API/index",
"iconPath": "static/image/icon_API.png",
"selectedIconPath": "static/image/icon_API_HL.png",
"text": "接口"
}],
"midButton": {
"width": "80px",
"height": "50px",
"text": "文字",
"iconPath": "static/image/midButton_iconPath.png",
"iconWidth": "24px",
"backgroundImage": "static/image/midButton_backgroundImage.png"
}
},
"easycom": {
"autoscan": true, //是否自动扫描组件
"custom": {//自定义扫描规则
"^uni-(.*)": "@/components/uni-$1.vue"
}
},
"topWindow": {
"path": "responsive/top-window.vue",
"style": {
"height": "44px"
}
},
"leftWindow": {
"path": "responsive/left-window.vue",
"style": {
"width": "300px"
}
},
"rightWindow": {
"path": "responsive/right-window.vue",
"style": {
"width": "300px"
},
"matchMedia": {
"minWidth": 768
}
}
}globalStyle
用于设置应用的状态栏、导航条、标题、窗口背景色等。
| 属性 | 类型 | 默认值 | 描述 | 平台差异说明 |
|---|---|---|---|---|
| navigationBarBackgroundColor | HexColor | #F8F8F8 | 导航栏背景颜色(同状态栏背景色) | APP与H5为#F8F8F8,小程序平台请参考相应小程序文档 |
| navigationBarTextStyle | String | black | 导航栏标题颜色及状态栏前景颜色,仅支持 black/white | |
| navigationBarTitleText | String | 导航栏标题文字内容 | ||
| navigationStyle | String | default | 导航栏样式,仅支持 default/custom。custom即取消默认的原生导航栏,需看使用注意 | 微信小程序 7.0+、H5 |
| backgroundColor | HexColor | #ffffff | 下拉显示出来的窗口的背景色 | 微信小程序 |
| backgroundTextStyle | String | dark | 下拉 loading 的样式,仅支持 dark / light | 微信小程序 |
| enablePullDownRefresh | Boolean | false | 是否开启下拉刷新,详见页面生命周期。 | |
| onReachBottomDistance | Number | 50 | 页面上拉触底事件触发时距页面底部距离,单位只支持px,详见页面生命周期 | uni-app x 不支持 |
| backgroundColorTop | HexColor | #ffffff | 顶部窗口的背景色(bounce回弹区域) | 仅 iOS 平台 |
| backgroundColorBottom | HexColor | #ffffff | 底部窗口的背景色(bounce回弹区域) | 仅 iOS 平台 |
| titleImage | String | 导航栏图片地址(替换当前文字标题),支付宝小程序内必须使用https的图片链接地址 | H5 | |
| transparentTitle | String | none | 导航栏整体(前景、背景)透明设置。支持 always 一直透明 / auto 滑动自适应 / none 不透明 | H5 |
| titlePenetrate | String | NO | 导航栏点击穿透 | H5 |
| pageOrientation | String | portrait | 横屏配置,屏幕旋转设置,仅支持 auto / portrait / landscape 详见 响应显示区域变化 | 微信小程序、QQ小程序 |
| animationDuration | Number | 300 | 窗口显示动画的持续时间,单位为 ms | |
| h5 | Object | 设置编译到 H5 平台的特定样式,配置项参考下方 H5 | H5 | |
| wx | Object | 设置编译到 wx 平台的特定样式,配置项参考下方 MP-WEIXIN | 微信小程序 | |
| tt | Object | 设置编译到 tt 平台的特定样式 | 抖音小程序 | |
| ks | Object | 设置编译到 ks 平台的特定样式 | 快手小程序 | |
| usingComponents | Object | 引用小程序组件,参考 小程序组件 | uni-app x 不支持 | |
| renderingMode | String | 同层渲染,webrtc(实时音视频) 无法正常时尝试配置 seperated 强制关掉同层 | 微信小程序 | |
| leftWindow | Boolean | true | 当存在 leftWindow 时,默认是否显示 leftWindow | H5 |
| topWindow | Boolean | true | 当存在 topWindow 时,默认是否显示 topWindow | H5 |
| rightWindow | Boolean | true | 当存在 rightWindow 时,默认是否显示 rightWindow | H5 |
| rpxCalcMaxDeviceWidth | Number | 960 | rpx 计算所支持的最大设备宽度,单位 px | H5 |
| rpxCalcBaseDeviceWidth | Number | 375 | rpx 计算使用的基准设备宽度,设备实际宽度超出 rpx 计算所支持的最大设备宽度时将按基准宽度计算,单位 px | H5 |
| rpxCalcIncludeWidth | Number | 750 | rpx 计算特殊处理的值,始终按实际的设备宽度计算,单位 rpx | H5 |
| maxWidth | Number | 单位px,当浏览器可见区域宽度大于maxWidth时,两侧留白,当小于等于maxWidth时,页面铺满;不同页面支持配置不同的maxWidth;maxWidth = leftWindow(可选)+page(页面主体)+rightWindow(可选) | H5 |
注意
- 支付宝小程序使用
titleImage时必须使用https的图片链接地址,需要真机调试才能看到效果,支付宝开发者工具内无效果 globalStyle中设置的titleImage也会覆盖掉pages->style内的设置文字标题- 使用
maxWidth时,页面内fixed元素需要使用--window-left,--window-right来保证布局位置正确
topWindow
以现有的手机应用为mainWindow,在左、上、右,可以追加新的页面显示窗体。
整体的宽屏适配思路,参考单独的宽屏适配指南
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| path | String | 配置页面路径 | |
| style | Object | 配置页面窗口表现,配置项参考下方 pageStyle | |
| matchMedia | Object | 配置显示该窗口的规则,配置项参考下方 matchMedia |
注意
- 目前 style 节点仅支持配置 width,height 等 css 样式相关属性
- 如果需求当存在 topwindow 时,自动隐藏页面的 navigationBar,根据需求不同在
App.vue中配置如下 css:- 只需要隐藏某个的页面 navigationBar
css/* 隐藏路径为 pages/component/view/view 页面的 navigationBar */ .qin-app--showtopwindow [data-page="pages/component/view/view"] qin-page-head { display: none; }/* 隐藏路径为 pages/component/view/view 页面的 navigationBar */ .qin-app--showtopwindow [data-page="pages/component/view/view"] qin-page-head { display: none; }- 需要隐藏大部分页面的 navigationBar,显示某个页面的 navigationBar
css/* 隐藏所有页面的 navigationBar */ .qin-app--showtopwindow qin-page-head { display: none; } /* 显示路径为 pages/component/view/view 页面的 navigationBar */ .qin-app--showtopwindow [data-page="pages/component/view/view"] qin-page-head { display: block; }/* 隐藏所有页面的 navigationBar */ .qin-app--showtopwindow qin-page-head { display: none; } /* 显示路径为 pages/component/view/view 页面的 navigationBar */ .qin-app--showtopwindow [data-page="pages/component/view/view"] qin-page-head { display: block; }
matchMedia
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| minWidth | Number | 768 | 当设备可见区域宽度 >= minWidth 时,显示该 window |
通过matchMedia的调节,可以自适应在不同屏幕上显示指定的window。
json
{
"pages": [
{
"path": "pages/login/login",
"style": {
"topWindow": false, // 当前页面不显示 topWindow
"leftWindow": false, // 当前页面不显示 leftWindow
"rightWindow": false // 当前页面不显示 rightWindow
}
}
],
"topWindow": {
"path": "responsive/top-window.vue", // 指定 topWindow 页面文件
"style": {
"height": "44px"
}
},
"leftWindow": {
"path": "responsive/left-window.vue", // 指定 leftWindow 页面文件
"style": {
"width": "300px"
}
},
"rightWindow": {
"path": "responsive/right-window.vue", // 指定 rightWindow 页面文件
"style": {
"width": "300px" // 页面宽度
},
"matchMedia": {
"minWidth": 768 //生效条件,当窗口宽度大于768px时显示
}
}
}{
"pages": [
{
"path": "pages/login/login",
"style": {
"topWindow": false, // 当前页面不显示 topWindow
"leftWindow": false, // 当前页面不显示 leftWindow
"rightWindow": false // 当前页面不显示 rightWindow
}
}
],
"topWindow": {
"path": "responsive/top-window.vue", // 指定 topWindow 页面文件
"style": {
"height": "44px"
}
},
"leftWindow": {
"path": "responsive/left-window.vue", // 指定 leftWindow 页面文件
"style": {
"width": "300px"
}
},
"rightWindow": {
"path": "responsive/right-window.vue", // 指定 rightWindow 页面文件
"style": {
"width": "300px" // 页面宽度
},
"matchMedia": {
"minWidth": 768 //生效条件,当窗口宽度大于768px时显示
}
}
}leftWindow
与topWindow相同
rightWindow
与topWindow相同
窗口通信参考:https://uniapp.dcloud.net.cn/api/window/communication
pages
qinjs 通过 pages 节点配置应用由哪些页面组成,pages 节点接收一个数组,数组每个项都是一个对象,其属性值如下:
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| path | String | 配置页面路径 | |
| style | Object | 配置页面窗口表现,配置项参考下方 pageStyle | |
| routers | Object | 页面定制,配置项参考下方 pageRouters |
Tips:
- pages节点的第一项为应用入口页(即首页)
- 应用中新增/减少页面,都需要对 pages 数组进行修改
- 文件名不需要写后缀,框架会自动寻找路径下的页面资源
代码示例:
开发目录为:
shell
┌─pages
│ ├─index
│ │ └─index.vue
│ └─login
│ └─login.vue
├─static
├─main.js
├─App.vue
├─manifest.json
└─pages.json┌─pages
│ ├─index
│ │ └─index.vue
│ └─login
│ └─login.vue
├─static
├─main.js
├─App.vue
├─manifest.json
└─pages.json则需要在 pages.json 中填写
js
{
"pages": [
{
"path": "pages/index/index",
"routers": { ... },
"style": { ... }
}, {
"path": "pages/login/login",
"routers": { ... },
"style": { ... }
}
]
}{
"pages": [
{
"path": "pages/index/index",
"routers": { ... },
"style": { ... }
}, {
"path": "pages/login/login",
"routers": { ... },
"style": { ... }
}
]
}routers
qinjs 通过 pages 节点配置应用由哪些页面组成,pages 节点接收一个数组,数组每个项都是一个对象,其属性值如下:
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| path | String | H5 真实的路径,支持路径参数。如: /home/:id | |
| name | String | qin.navigateTo 、 qin.redirectTo 、 qin.switchTab 、 qin.reLaunch 可使用 name 参数进行跳转 |
style
用于设置每个页面的状态栏、导航条、标题、窗口背景色等。
页面中配置项会覆盖 globalStyle 中相同的配置项
| 属性 | 类型 | 默认值 | 描述 | 平台差异说明 |
|---|---|---|---|---|
| navigationBarBackgroundColor | HexColor | #F8F8F8 | 导航栏背景颜色(同状态栏背景色) | APP与H5为#F8F8F8,小程序平台请参考相应小程序文档 |
| navigationBarTextStyle | String | black | 导航栏标题颜色及状态栏前景颜色,仅支持 black/white | |
| navigationBarTitleText | String | 导航栏标题文字内容 | ||
| navigationBarShadow | Object | 导航栏阴影,配置参考下方 导航栏阴影 | ||
| navigationStyle | String | default | 导航栏样式,仅支持 default/custom。custom即取消默认的原生导航栏,需看使用注意 | 微信小程序 7.0+、H5 |
| disableScroll | Boolean | false | 设置为 true 则页面整体不能上下滚动(bounce效果),只在页面配置中有效,在globalStyle中设置无效 | 微信小程序(iOS) |
| backgroundColor | HexColor | #ffffff | 窗口的背景色 | 微信小程序、抖音小程序 |
| backgroundTextStyle | String | dark | 下拉 loading 的样式,仅支持 dark/light | |
| enablePullDownRefresh | Boolean | false | 是否开启下拉刷新,详见页面生命周期。 | |
| onReachBottomDistance | Number | 50 | 页面上拉触底事件触发时距页面底部距离,单位只支持px,详见页面生命周期 | |
| titleImage | String | 导航栏图片地址(替换当前文字标题),支付宝小程序内必须使用https的图片链接地址 | H5 | |
| transparentTitle | String | none | 导航栏透明设置。支持 always 一直透明 / auto 滑动自适应 / none 不透明 | H5 |
| titlePenetrate | String | NO | 导航栏点击穿透 | H5 |
| h5 | Object | 设置编译到 H5 平台的特定样式,配置项参考下方 H5 | H5 | |
| wx | Object | 设置编译到 wx 平台的特定样式 | 微信小程序 | |
| tt | Object | 设置编译到 tt 平台的特定样式 | 抖音小程序 | |
| usingComponents | Object | 引用小程序组件,参考 小程序组件 | 、微信小程序、京东小程序 | |
| leftWindow | Boolean | true | 当存在 leftWindow时,当前页面是否显示 leftWindow | H5 |
| topWindow | Boolean | true | 当存在 topWindow 时,当前页面是否显示 topWindow | H5 |
| rightWindow | Boolean | true | 当存在 rightWindow时,当前页面是否显示 rightWindow | H5 |
| maxWidth | Number | 单位px,当浏览器可见区域宽度大于maxWidth时,两侧留白,当小于等于maxWidth时,页面铺满;不同页面支持配置不同的maxWidth;maxWidth = leftWindow(可选)+page(页面主体)+rightWindow(可选) | H5(2.9.9+) |
注意
- 使用
maxWidth时,页面内fixed元素需要使用--window-left,--window-right来保证布局位置正确
代码示例:
js
{
"pages": [{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",//设置页面标题文字
"enablePullDownRefresh":true//开启下拉刷新
}
},
...
]
}{
"pages": [{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",//设置页面标题文字
"enablePullDownRefresh":true//开启下拉刷新
}
},
...
]
}自定义导航栏使用注意
当 navigationStyle 设为 custom 或 titleNView 设为 false 时,原生导航栏不显示,此时要注意几个问题:
- 非 H5 端,手机顶部状态栏区域会被页面内容覆盖。这是因为窗体是沉浸式的原因,即全屏可写内容。 qinjs 提供了状态栏高度的css变量--status-bar-height,如果需要把状态栏的位置从前景部分让出来,可写一个占位 div ,高度设为 css 变量。
html
<template>
<view>
<view class="status_bar">
<!-- 这里是状态栏 -->
</view>
<view> 状态栏下的文字 </view>
</view>
</template>
<style>
.status_bar {
height: var(--status-bar-height);
width: 100%;
}
</style><template>
<view>
<view class="status_bar">
<!-- 这里是状态栏 -->
</view>
<view> 状态栏下的文字 </view>
</view>
</template>
<style>
.status_bar {
height: var(--status-bar-height);
width: 100%;
}
</style>- 如果原生导航栏不能满足需求,推荐使用 qin ui 的自定义导航栏NavBar。这个前端导航栏自动处理了状态栏高度占位问题。
- 前端导航栏搭配原生下拉刷新时,会有问题,包括
- 微信小程序下iOS需要拉更长才能看到下拉刷新的三个点,而Android是从屏幕顶部下拉,无法从导航栏下方下拉。如果一定要从前端导航栏下拉,小程序下只能放弃原生下拉刷新,纯前端模拟,参考mescroll插件,但这样很容易产生性能问题。目前小程序平台自身没有提供更好的方案
- H5下,原生下拉刷新提供了circle样式,可以指定offset偏移量(pages.json的app-plus下配置),自定义下拉圈出现的位置。在hello uni-app的扩展组件中有示例。
- 非H5端,前端导航盖不住原生组件。如果页面有video、map、textarea(仅小程序)等原生组件,滚动时会覆盖住导航栏
- 如果是小程序下,可以使用cover-view来做导航栏,避免覆盖问题
- 前端组件在渲染速度上不如原生导航栏,原生导航可以在动画期间渲染,保证动画期间不白屏,但使用前端导航栏,在新窗体进入的动画期间可能会整页白屏,越低端的手机越明显。
- 页面禁用原生导航栏后,想要改变状态栏的前景字体样式,仍可设置页面的 navigationBarTextStyle 属性(只能设置为 black或white)。
h5
配置编译到 H5 平台时的特定样式
| 属性 | 类型 | 描述 |
|---|---|---|
| titleNView | Object | 导航栏 |
| pullToRefresh | Object | 下拉刷新 |
导航栏
| 属性 | 类型 | 默认值 | 描述 | 最低版本 |
|---|---|---|---|---|
| backgroundColor | String | #F7F7F7 | 背景颜色,颜色值格式为"#RRGGBB"。 | |
| buttons | Array | 自定义按钮,参考 buttons | ||
| titleColor | String | #000000 | 标题文字颜色 | |
| titleText | String | 标题文字内容 | ||
| titleSize | String | 标题文字字体大小 | ||
| type | String | default | 导航栏样式。"default"-默认样式;"transparent"-透明渐变。 | |
| searchInput | Object | 导航栏上的搜索框样式,详见:searchInput | 1.6.5 |
自定义按钮
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| type | String | none | 按钮样式 |
| color | String | 默认与标题文字颜色一致 | 按钮上文字颜色 |
| background | String | 默认值为灰色半透明 | 按钮的背景颜色,仅在标题栏type=transparent时生效 |
| badgeText | String | 按钮上显示的角标文本,最多显示3个字符,超过则显示为... | |
| colorPressed(暂不支持) | String | 默认值为 color 属性值自动调整透明度为 0.3 | 按下状态按钮文字颜色 |
| float | String | right | 按钮在标题栏上的显示位置,可取值"left"、"right" |
| fontWeight | String | normal | 按钮上文字的粗细。可取值"normal"-标准字体、"bold"-加粗字体。 |
| fontSize | String | 按钮上文字大小 | |
| fontSrc | String | 按钮上文字使用的字体文件路径。 | |
| select | String | false | 是否显示选择指示图标(向下箭头) |
| text | String | 按钮上显示的文字。使用字体图标时 unicode 字符表示必须 '\u' 开头,如 "\ue123"(注意不能写成"\e123")。 | |
| width | String | 44px | 按钮的宽度,可取值: "*px" - 逻辑像素值,如"10px"表示10逻辑像素值,不支持rpx,按钮的内容居中显示; "auto" - 自定计算宽度,根据内容自动调整按钮宽度 |
按钮样式
使用 type 值设置按钮的样式时,会忽略 fontSrc 和 text 属性。
| 值 | 说明 |
|---|---|
| forward | 前进按钮 |
| back | 后退按钮 |
| share | 分享按钮 |
| favorite | 收藏按钮 |
| home | 主页按钮 |
| menu | 菜单按钮 |
| close | 关闭按钮 |
| none | 无样式,需通过 text 属性设置按钮上显示的内容、通过 fontSrc 属性设置使用的字体库。 |
下拉刷新
h5 平台下拉刷新动画,只有 circle 类型。
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| color | String | #2BD009 | 颜色值格式为"#RRGGBB" |
| offset | String | 0px | 下拉刷新控件的起始位置。支持百分比,如"10%";像素值,如"50px",不支持rpx。 |
搜索框样式
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| autoFocus | Boolean | false | 是否自动获取焦点 |
| align | String | center | 非输入状态下文本的对齐方式。可取值: "left" - 居左对齐; "right" - 居右对齐; "center" - 居中对齐。 |
| backgroundColor | String | rgba(255,255,255,0.5) | 背景颜色 |
| borderRadius | String | 0px | 输入框的圆角半径,取值格式为"XXpx",其中XX为像素值(逻辑像素),不支持rpx。 |
| placeholder | String | 提示文本 | |
| placeholderColor | String | #CCCCCC | 提示文本颜色 |
| disabled | Boolean | false | 是否可输入 |
注意事项:
- 如果
h5节点没有配置,默认会使用app-plus下的配置。 - 配置了
h5节点,则会覆盖app-plus下的配置。
navigationBarShadow
| 属性 | 类型 | 描述 |
|---|---|---|
| colorType | String | 阴影的颜色,支持:grey、blue、green、orange、red、yellow |
注意事项:
- 微信 需要配置: "disableScroll": true
- 支付宝 "mp-alipay":
wx
配置编译到 MP-WEIXIN 平台时的特定样式
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| homeButton | Boolean | false | 在非首页、非页面栈最底层页面或非tabbar内页面中的导航栏展示home键 |
| backgroundColorTop | HexColor | #ffffff | 顶部窗口的背景色,仅 iOS 支持 |
| backgroundColorBottom | HexColor | #ffffff | 底部窗口的背景色,仅 iOS 支持 |
| restartStrategy | String | homePage | 重新启动策略配置。支持 homePage / homePageAndLatestPage |
| initialRenderingCache | String | 页面初始渲染缓存配置。支持 static / dynamic | |
| visualEffectInBackground | String | none | 切入系统后台时,隐藏页面内容,保护用户隐私。支持 hidden / none |
| handleWebviewPreload | String | static | 控制预加载下个页面的时机。支持 static / manual / auto |
FAQ
- Q:如何取消原生导航栏?或自定义导航
- A:参考导航栏开发指南
easycom
传统vue组件,需要安装、引用、注册,三个步骤后才能使用组件。easycom将其精简为一步。
只要组件路径符合规范(具体见下),就可以不用引用、注册,直接在页面中使用。如下:
html
<template>
<view class="container">
<comp-a></comp-a>
<uni-list>
</uni-list>
</view>
</template>
<script>
// 这里不用import引入,也不需要在components内注册uni-list组件。template里就可以直接用
export default {
data() {
return {}
}
}
</script><template>
<view class="container">
<comp-a></comp-a>
<uni-list>
</uni-list>
</view>
</template>
<script>
// 这里不用import引入,也不需要在components内注册uni-list组件。template里就可以直接用
export default {
data() {
return {}
}
}
</script>路径规范指:
- 安装在项目根目录的components目录下,并符合
components/组件名称/组件名称.vue - 安装在 qin_modules 下,路径为
qin_modules/插件ID/components/组件名称/组件名称.vue
工程目录:
shell
┌─components
│ └─comp-a
│ └─comp-a.vue 符合easycom规范的组件
└─qin_modules [qin_module](/qin_modules)中符合easycom规范的组件
└─qin_modules
└─qinui-list
└─components
└─qinui-list
└─ qinui-list.vue┌─components
│ └─comp-a
│ └─comp-a.vue 符合easycom规范的组件
└─qin_modules [qin_module](/qin_modules)中符合easycom规范的组件
└─qin_modules
└─qinui-list
└─components
└─qinui-list
└─ qinui-list.vue不管components目录下安装了多少组件,easycom打包会自动剔除没有使用的组件,对组件库的使用尤为友好。
组件库批量安装,随意使用,自动按需打包。以官方的qin-ui为例,在HBuilderX新建项目界面选择qin-ui项目模板,只需在页面中敲u,拉出大量组件代码块,直接选择,即可使用。大幅提升开发效率,降低使用门槛。
在uni-app插件市场下载符合components/组件名称/组件名称.vue目录结构的组件,均可直接使用。
自定义easycom配置的示例
easycom是自动开启的,不需要手动开启,有需求时可以在pages.json的easycom节点进行个性化设置,如关闭自动扫描,或自定义扫描匹配组件的策略。设置参数如下:
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| autoscan | Boolean | true | 是否开启自动扫描,开启后将会自动扫描符合components/组件名称/组件名称.vue目录结构的组件 |
| custom | Object | - | 以正则方式自定义组件匹配规则。如果autoscan不能满足需求,可以使用custom自定义匹配规则 |
如果你的组件,不符合easycom前述的路径规范。可以在pages.json的easycom节点中自行定义路径规范。
如果需要匹配node_modules内的vue文件,需要使用packageName/path/to/vue-file-$1.vue形式的匹配规则,其中packageName为安装的包名,/path/to/vue-file-$1.vue为vue文件在包内的路径。
json
"easycom": {
"autoscan": true,
"custom": {
"^uni-(.*)": "@/components/uni-$1.vue", // 匹配components目录内的vue文件
"^vue-file-(.*)": "packageName/path/to/vue-file-$1.vue" // 匹配node_modules内的vue文件
}
}"easycom": {
"autoscan": true,
"custom": {
"^uni-(.*)": "@/components/uni-$1.vue", // 匹配components目录内的vue文件
"^vue-file-(.*)": "packageName/path/to/vue-file-$1.vue" // 匹配node_modules内的vue文件
}
}说明
easycom方式引入的组件无需在页面内import,也不需要在components内声明,即可在任意页面使用。easycom方式引入组件不是全局引入,而是局部引入。例如在H5端只有加载相应页面才会加载使用的组件。- 在组件名完全一致的情况下,
easycom引入的优先级低于手动引入(区分连字符形式与驼峰形式)。 - 考虑到编译速度,直接在
pages.json内修改easycom不会触发重新编译,需要改动页面内容触发。 easycom只处理vue组件,不处理小程序专用组件(如微信的wxml格式组件)。不处理后缀为.nvue的组件。因为nvue页面引入的组件也是.vue组件。可以参考uni ui,使用vue后缀,同时兼容nvue页面。
tabBar
如果应用是一个多 tab 应用,可以通过 tabBar 配置项指定一级导航栏,以及 tab 切换时显示的对应页。
在 pages.json 中提供 tabBar 配置,不仅仅是为了方便快速开发导航,更重要的是在App和小程序端提升性能。在这两个平台,底层原生引擎在启动时无需等待js引擎初始化,即可直接读取 pages.json 中配置的 tabBar 信息,渲染原生tab。
Tips
- 当设置 position 为 top 时,将不会显示 icon
- tabBar 中的 list 是一个数组,只能配置最少2个、最多5个 tab,tab 按数组的顺序排序。
- tabbar 切换第一次加载时可能渲染不及时,可以在每个tabbar页面的onLoad生命周期里先弹出一个等待雪花(hello uni-app使用了此方式)
- tabbar 的页面展现过一次后就保留在内存中,再次切换 tabbar 页面,只会触发每个页面的onShow,不会再触发onLoad。
- 顶部的 tabbar 目前仅微信小程序上支持。需要用到顶部选项卡的话,建议不使用 tabbar 的顶部设置,而是自己做顶部选项卡,可参考 hello uni-app->模板->顶部选项卡。
属性说明:
| 属性 | 类型 | 必填 | 默认值 | 描述 | 平台差异说明 |
|---|---|---|---|---|---|
| color | HexColor | 是 | tab 上的文字默认颜色 | ||
| selectedColor | HexColor | 是 | tab 上的文字选中时的颜色 | ||
| backgroundColor | HexColor | 是 | tab 的背景色 | ||
| borderStyle | String | 否 | black | tabbar 上边框的颜色,可选值 black/white,也支持其他颜色值 | H5 |
| blurEffect | String | 否 | none | iOS 高斯模糊效果,可选值 dark/extralight/light/none(参考:使用说明) | H5(只有最新版浏览器才支持) |
| list | Array | 是 | tab 的列表,详见 list 属性说明,最少2个、最多5个 tab | ||
| position | String | 否 | bottom | 可选值 bottom、top | top 值仅微信小程序支持 |
| fontSize | String | 否 | 10px | 文字默认大小 | H5 |
| iconWidth | String | 否 | 24px | 图标默认宽度(高度等比例缩放) | H5 |
| spacing | String | 否 | 3px | 图标和文字的间距 | H5 |
| height | String | 否 | 50px | tabBar 默认高度 | H5 |
| midButton | Object | 否 | 中间按钮 仅在 list 项为偶数时有效 | H5 | |
| iconfontSrc | String | 否 | list设置 iconfont 属性时,需要指定字体文件路径 | H5 | |
| backgroundImage | String | 否 | 设置背景图片,优先级高于 backgroundColor | ||
| backgroundRepeat | String | 否 | 设置标题栏的背景图平铺方式,可取值:"repeat" - 背景图片在垂直方向和水平方向平铺;"repeat-x" - 背景图片在水平方向平铺,垂直方向拉伸;"repeat-y" - 背景图片在垂直方向平铺,水平方向拉伸;"no-repeat" - 背景图片在垂直方向和水平方向都拉伸。 默认使用 "no-repeat" | ||
| redDotColor | String | 否 | tabbar上红点颜色 |
其中 list 接收一个数组,数组中的每个项都是一个对象,其属性值如下:
| 属性 | 类型 | 必填 | 说明 | 平台差异 |
|---|---|---|---|---|
| pagePath | String | 是 | 页面路径,必须在 pages 中先定义 | |
| text | String | 是 | tab 上按钮文字,在 H5 平台为非必填。例如中间可放一个没有文字的+号图标 | |
| iconPath | String | 否 | 图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px,当 position 为 top 时,此参数无效,不支持网络图片,不支持字体图标 | |
| selectedIconPath | String | 否 | 选中时的图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px ,当 position 为 top 时,此参数无效 | |
| visible | Boolean | 否 | 该项是否显示,默认显示 | H5 |
| iconfont | Object | 否 | 字体图标,优先级高于 iconPath | H5 |
midButton 属性说明
| 属性 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| width | String | 否 | 80px | 中间按钮的宽度,tabBar 其它项为减去此宽度后平分,默认值为与其它项平分宽度 |
| height | String | 否 | 50px | 中间按钮的高度,可以大于 tabBar 高度,达到中间凸起的效果 |
| text | String | 否 | 中间按钮的文字 | |
| iconPath | String | 否 | 中间按钮的图片路径 | |
| iconWidth | String | 否 | 24px | 图片宽度(高度等比例缩放) |
| backgroundImage | String | 否 | 中间按钮的背景图片路径 | |
| iconfont | Object | 否 | 字体图标,优先级高于 iconPath |
midButton没有pagePath,需监听点击事件,自行处理点击后的行为逻辑。监听点击事件为调用API:uni.onTabBarMidButtonTap,详见https://uniapp.dcloud.io/api/ui/tabbar?id=ontabbarmidbuttontap
iconfont参数说明:
| 属性 | 类型 | 说明 |
|---|---|---|
| text | String | 字库 Unicode 码 |
| selectedText | String | 选中后字库 Unicode 码 |
| fontSize | String | 字体图标字号(px) |
| color | String | 字体图标颜色 |
| selectedColor | String | 字体图标选中颜色 |
tabbar常见问题
- tabbar 的 js api 见接口-界面-tabbar,可实现动态显示隐藏(如弹出层无法覆盖tabbar)、内容修改(、item加角标等功能。hello uni-app中也有示例。
- tabbar 的 item 点击事件见页面生命周期的onTabItemTap。
- 代码跳转到 tabbar 页面,api只能使用qin.replace,不能使用 qin.navigateTo、qin.redirectTo;
- tabbar 的默认高度,在不同平台不一样。开发者也可以自行设定高度,调回56px。详见
- tabbar 在H5端是div模拟的,属于前端屏幕窗口的一部分,如果要使用bottom居底定位方式,应该使用css变量
--window-bottom,比如悬浮在tabbar上方10px的按钮,样式如下bottom: calc(var(--window-bottom) + 10px) - 中间带+号的tabbar模板例子,参考。可跨端,但+号不凸起。如需中间凸起,配置tabbar的midButton。
- 前端弹出遮罩层挡不住tabbar的问题,跨端处理方式时动态隐藏tabbar。
- 微信小程序模拟器1.02.1904090版有bug,在缩放模拟器页面百分比后,tabbar点击多次后就会卡死。真机无碍,使用时注意。详见
代码示例
json
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/component/index",
"iconPath": "static/image/icon_component.png",
"selectedIconPath": "static/image/icon_component_HL.png",
"text": "组件"
}, {
"pagePath": "pages/API/index",
"iconPath": "static/image/icon_API.png",
"selectedIconPath": "static/image/icon_API_HL.png",
"text": "接口"
}]
}"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/component/index",
"iconPath": "static/image/icon_component.png",
"selectedIconPath": "static/image/icon_component_HL.png",
"text": "组件"
}, {
"pagePath": "pages/API/index",
"iconPath": "static/image/icon_API.png",
"selectedIconPath": "static/image/icon_API_HL.png",
"text": "接口"
}]
}自定义tabbar
TODO
condition
启动模式配置,仅开发期间生效,用于模拟直达页面的场景,如:小程序转发后,用户点击所打开的页面。
属性说明:
| 属性 | 类型 | 是否必填 | 描述 |
|---|---|---|---|
| current | Number | 是 | 当前激活的模式,list节点的索引值 |
| list | Array | 是 | 启动模式列表 |
list说明:
| 属性 | 类型 | 是否必填 | 描述 |
|---|---|---|---|
| name | String | 是 | 启动模式名称 |
| path | String | 是 | 启动页面路径 |
| query | String | 否 | 启动参数,可在页面的 onLoad 函数里获得 |
注意: 在微信开发者工具里需要手动改变编译模式,如下图:

代码示例:
js
"condition": { //模式配置,仅开发期间生效
"current": 0, //当前激活的模式(list 的索引项)
"list": [{
"name": "swiper", //模式名称
"path": "pages/component/swiper/swiper", //启动页面,必选
"query": "interval=4000&autoplay=false" //启动参数,在页面的onLoad函数里面得到。
},
{
"name": "test",
"path": "pages/component/switch/switch"
}
]
}"condition": { //模式配置,仅开发期间生效
"current": 0, //当前激活的模式(list 的索引项)
"list": [{
"name": "swiper", //模式名称
"path": "pages/component/swiper/swiper", //启动页面,必选
"query": "interval=4000&autoplay=false" //启动参数,在页面的onLoad函数里面得到。
},
{
"name": "test",
"path": "pages/component/switch/switch"
}
]
}subPackages
分包加载配置,此配置为小程序的分包加载机制。
因小程序有体积和资源加载限制,各家小程序平台提供了分包方式,优化小程序的下载和启动速度。
所谓的主包,即放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本;而分包则是根据pages.json的配置进行划分。
在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,会把对应分包自动下载下来,下载完成后再进行展示。此时终端界面会有等待提示。
其目的不用于下载提速,而用于首页是 vue 时的启动提速。
subPackages 节点接收一个数组,数组每一项都是应用的子包,其属性值如下:
| 属性 | 类型 | 是否必填 | 描述 |
|---|---|---|---|
| root | String | 是 | 子包的根目录 |
| pages | Array | 是 | 子包由哪些页面组成,参数同 pages |
注意:
subPackages里的pages的路径是root下的相对路径,不是全路径。- 微信小程序每个分包的大小是2M,总体积一共不能超过20M。
- 抖音小程序每个分包的大小是2M,总体积一共不能超过16M(抖音小程序基础库 1.88.0 及以上版本开始支持,抖音小程序开发者工具请使用大于等于 2.0.6 且小于 3.0.0 的版本)。
- 快手小程序每个分包的大小是2M,总体积一共不能超过24M。
- 分包下支持独立的
static目录,用来对静态资源进行分包。 qinjs内支持对微信小程序``抖音小程序、快手小程序分包优化,即将静态资源或者js文件放入分包内不占用主包大小。详情请参考:关于分包优化的说明- 针对
vendor.js过大的情况可以使用运行时压缩代码cli创建的项目可以在package.json中添加参数--minimize,示例:"dev:wx": "cross-env NODE_ENV=development UNI_PLATFORM=wx vue-cli-service uni-build --watch --minimize"
使用方法:
假设支持分包的 qinjs 目录结构如下:
shell
┌─pages
│ ├─index
│ │ └─index.vue
│ └─login
│ └─login.vue
├─pagesA
│ ├─static
│ └─list
│ └─list.vue
├─pagesB
│ ├─static
│ └─detail
│ └─detail.vue
├─static
├─main.js
├─App.vue
├─manifest.json
└─pages.json┌─pages
│ ├─index
│ │ └─index.vue
│ └─login
│ └─login.vue
├─pagesA
│ ├─static
│ └─list
│ └─list.vue
├─pagesB
│ ├─static
│ └─detail
│ └─detail.vue
├─static
├─main.js
├─App.vue
├─manifest.json
└─pages.json则需要在 pages.json 中填写
js
{
"pages": [{
"path": "pages/index/index",
"style": { ...}
}, {
"path": "pages/login/login",
"style": { ...}
}],
"subPackages": [{
"root": "pagesA",
"pages": [{
"path": "list/list",
"style": { ...}
}]
}, {
"root": "pagesB",
"pages": [{
"path": "detail/detail",
"style": { ...}
}]
}],
"preloadRule": {
"pagesA/list/list": {
"network": "all",
"packages": ["__APP__"]
},
"pagesB/detail/detail": {
"network": "all",
"packages": ["pagesA"]
}
}
}{
"pages": [{
"path": "pages/index/index",
"style": { ...}
}, {
"path": "pages/login/login",
"style": { ...}
}],
"subPackages": [{
"root": "pagesA",
"pages": [{
"path": "list/list",
"style": { ...}
}]
}, {
"root": "pagesB",
"pages": [{
"path": "detail/detail",
"style": { ...}
}]
}],
"preloadRule": {
"pagesA/list/list": {
"network": "all",
"packages": ["__APP__"]
},
"pagesB/detail/detail": {
"network": "all",
"packages": ["pagesA"]
}
}
}preloadRule
分包预载配置。
配置preloadRule后,在进入小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度
preloadRule 中,key 是页面路径,value 是进入此页面的预下载配置,每个配置有以下几项:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| packages | StringArray | 是 | 无 | 进入页面后预下载分包的 root 或 name。__APP__ 表示主包。 |
| network | String | 否 | wifi | 在指定网络下预下载,可选值为:all(不限网络)、wifi(仅wifi下预下载) |
app的分包,同样支持preloadRule,但网络规则无效。
本地调试@local
在日常开发往往会有一些关于 pages.json 不想提交到代码仓库的配置,这时候 qinjs 支持本地配置的。在 .gitignore 中添加 *.local* 即可被 git 忽略。
sh
pages.json
pages.local.json
pages.h5.json
pages.h5.local.json
pages.wx.json
pages.wx.local.json
pages.tt.json
pages.tt.local.jsonpages.json
pages.local.json
pages.h5.json
pages.h5.local.json
pages.wx.json
pages.wx.local.json
pages.tt.json
pages.tt.local.json运行抖音小程序加载优先级
pages.tt.local.json (抖音配置本地) > pages.tt.json (抖音配置) > pages.local.json (默认本地配置) > pages.json (默认配置)
运行微信小程序加载优先级
pages.wx.local.json (微信配置本地) > pages.wx.json (微信配置) > pages.local.json (默认本地配置) > pages.json (默认配置)
运行 H5 加载优先级
pages.h5.local.json (抖音配置本地) > pages.h5.json (抖音配置) > pages.local.json (默认本地配置) > pages.json (默认配置)
单独调试某一个页面
当项目比较大的时候小程序开发工具编译有时候会比较慢。特别是低端电脑打开页面和组件比较多的项目的时候,没保存一下需要等待1分钟甚至更多小程序开发工具才会有反应,甚至有时候等了10分钟依然没有反应。可设置 compilePages 和 compileSubPackages 单独编译某个文件,加速小程序开发工具的编译速度,提高开发效率。
json
"compilePages": [
{
"path": "pages/index/index",
"routers": {
"name": "Home",
"path": "/"
},
"style": {
"navigationBarTitleText": "INDEX_QIN_JS"
}
}
],
"compileSubPackages": [
{
"root": "pack1",
"pages": [
{
"path": "pages/pack1-page1/index",
"routers": {
"name": "Pack1Page1",
"path": "/pack1/page1"
},
"style": {
"navigationBarTitleText": "PACK1_PAGE1_QIN_JS"
}
}
]
}
]"compilePages": [
{
"path": "pages/index/index",
"routers": {
"name": "Home",
"path": "/"
},
"style": {
"navigationBarTitleText": "INDEX_QIN_JS"
}
}
],
"compileSubPackages": [
{
"root": "pack1",
"pages": [
{
"path": "pages/pack1-page1/index",
"routers": {
"name": "Pack1Page1",
"path": "/pack1/page1"
},
"style": {
"navigationBarTitleText": "PACK1_PAGE1_QIN_JS"
}
}
]
}
]extends
可以集成集体配置。 ./pages.base.json 中支持 pages.json 所有配置。
json
{
"extends": "./pages.base.json"
}{
"extends": "./pages.base.json"
}本地调试
pages.json 也支持 pages.local.json 本地调试,我们可以把 .local.json 忽略 git 提交。
FAQ
- Q:为什么在 pages.json 里配置小程序定位权限描述,无法编译到小程序端,运行后一直提示 getLocation 需要在 app.json 中声明
- A:微信小程序的权限描述配置在 manifest 中,不在 pages.json 中,具体参考文档