更新记录
v1.0(2021-06-12) 下载此版本
完成 梦学谷在线教育学习平台,知识付费,博客社区,自定义视频播放器组件支持倍速播放,支持支付宝微信支付,安卓IOS微信小程序多端适配,手机验证码登录注册
平台兼容性
uni-app 入门与环境搭建
学习本套课程需要储备Vue.js全家桶知识,课程地址:
- https://item.taobao.com/item.htm?id=596790926911
- https://ke.qq.com/course/466900
什么是 uni-app
uni-app
是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉/淘宝)、快应用等多个平台。
DCloud
公司拥有600万开发者用户,几十万应用案例、12亿手机端月活用户,数千款uni-app插件、70+微信/qq群。
uni-app
在手,做啥都不愁。即使不跨端,uni-app
也是更好的小程序开发框架(详见)、更好的App跨平台框架、更方便的H5开发框架。不管领导安排什么样的项目,你都可以快速交付,不需要转换开发思维、不需要更改开发习惯。
uni-app
使用 vue 的语法 + 小程序的标签和 API 。
安装开发工具 HBuilderX
-
什么是 HBuilderX
HBuilderX
,H是HTML的首字母,Builder是构造者,X是HBuilder的下一代版本。我们也简称HX
。HX
是轻如编辑器、强如IDE的合体版本,它是免费的。-
轻巧
仅10余M的绿色发行包(不含插件)
-
极速 不管是启动速度、大文档打开速度、编码提示,都极速响应 C++的架构性能远超Java或Electron架构
-
vue开发强化
HX
对vue做了大量优化投入,开发体验远超其他开发工具 详见 按下Alt+鼠标左键可直接打开网址 -
小程序支持 国外开发工具没有对中国的小程序开发优化,
HX
可新建uni-app
或小程序
、快应用
等项目,为国人提供更高效工具 -
markdown利器
HX
是唯一一个新建文件默认类型是markdown的编辑器,也是对md支持最强的编辑器HX
为md强化了众多功能,请务必点击【菜单-帮助-markdown语法示例】,快速掌握md及HX
的强化技巧! -
清爽护眼 HX的界面比其他工具更清爽简洁,绿柔主题经过科学的脑疲劳测试,是最适合人眼长期观看的主题界面 详见
-
强大的语法提示
HX
是中国唯一一家拥有自主IDE语法分析引擎的公司,对前端语言提供准确的代码提示和转到定义(Alt+鼠标左键) -
高效极客工具 更强大的多光标、智能双击...让字处理的效率大幅提升 了解
HX
的极客技巧,详见, -
更强的json支持 现代js开发中大量json结构的写法,
HX
提供了比其他工具更高效的操作 详见 -
丰富的快捷键
如果你习惯了其他工具(如vscode或sublime)的快捷键,在
菜单工具-快捷键
方案中可以切换。
-
-
下载 HBuilderX 开发工具
最新版本下载:https://www.dcloud.io/hbuilderx.html
HBuilderX历史版本下载地址: https://ask.dcloud.net.cn/article/37302
我们从历史版本中下载 2.9.3 ,如下图: ( ==不要用2.9.7+以上,新版本对 vedio 自定义视频播放竖/横屏有问题==)
-
下载好后,直接傻瓜式安装,安装后查看HuilderX版本,使用2.9.3.20201014版本
-
安装后,如果会弹出安装一个语法提示库插件,点击它进行安装(不弹就忽略它)。安装成功后,重启HuilderX
安装scss/sass编译
使用了scss/sass语法后需要编译为css。uni-app会自动编译或对文件右键-外部命令编译时使用。
-
浏览器访问下面链接,点击右侧
使用HBuilderX 入插件
> 弹出窗口点击打开HBuilderX
:https://ext.dcloud.net.cn/plugin?name=compile-node-sass
-
在 HuilderX 会弹出是否安装,点击
是
-
安装成功后,在页面的style标签上使用 lang="scss" 后即可编写scss代码
<style lang="scss"> </style>
创建项目
- 文件-新建-项目
- 打开新建项目窗口后,项目名
mxg-education-app
, 具体如下操作,
HBuilder 连接真机
HBuilder/HBuilderX真机运行、手机运行、真机联调常见问题 http://ask.dcloud.net.cn/article/97
Mac 连接iphone真机
新安装HBuilderX工具的要保证有App真机运行插件,有手机才会被HBuilder识别。
上面是预告,连接步骤:
-
确认手机已通过数据线连接电脑
-
电脑下载iTunes,确认iTunes能正常连接手机
(爱思官方可下:http://url.i4.cn/UjuIbiaa)
-
如手机屏幕弹出需信任本计算机的询问,请同意该授权
-
连接成功,在Hbuilder菜单栏上点击 运行 ,如下图就可以查看到手机型号,运行项目到手机上
如果显示未检测到设备,就是Hbuilder没有识别到,连接失败,参见官方说明 http://ask.dcloud.net.cn/article/97
-
运行后,查看控制台到如下日志,说明APP已经安装到手机,
-
打开手机,查看桌面上已经有一个
HBuilder
的APP后,当前点击app还打不开, -
然后如下操作后就可以打开APP了,步骤:
"设置"---》"通用"---》"设备管理" (或"描述文件"。这步app安装成功后才找得到)--- 》找到 Digital Heaven 开头的证书 》 信任
Mac连接Android手机
-
关于本机(指==Mac系统的关于本机==,非手机) --> 系统报告 -> usb -> 你所连接的device --> 厂商ID或者供应商ID(Vendor ID)
-
在终端执行如下命令:echo xxxxxx >> ~/.android/adb_usb.ini (“xxxxxx”为厂商ID或者供应商ID(Vendor ID),有些系统下echo命令并不能正确写入文件,可在~/.android/目录下修改或新建adb_usb.ini添加xxxxxx)
# 进入 ~ 目录 mengxuegu@mengxuegu ~ % cd ~ # 如果不存在android则创建 mengxuegu@mengxuegu ~ % mkdir android # 写入文件 mengxuegu@mengxuegu ~ % echo 0x17ef >> ~/android/adb_usb.ini # 查看下是否添加成功 mengxuegu@mengxuegu ~ % cat ~/android/adb_usb.ini 0x17ef
-
重启HBuilderX。
-
如重启HBuilderX仍然不行,请使用命令行(终端.app),切换到HBuilderX自带的adb目录。
-
HBuilderX正式版的adb目录位置:tools/adbs目录(MAC下为HBuilderX.app/Contents/tools/adbs目录)
-
HBuilderX Alpha版的adb目录位置:plugins/launcher/tools/adbs目录(MAC下为
/Applications/HBuilderX-Alpha.app/Contents/HBuilderX/plugins/launcher/tools/adbs
目录) -
在adbs目录下运行
./adb kill-server
重试。 -
重启电脑重试。
Windows连接Android手机
确认已安装Android手机驱动
。
如果手机连接没有任何反应或提示驱动问题,可通过以下方式解决:
- 装驱动比较好的方式是使用各种手机助手,比如
360、腾讯的各种手机助手
,如果有问题,尝试升级助手的版本。 - 打开手机开发者模式,(不同机型打开方式不一样,自行百度)一般是找到机器版本号。如打开开发者模式:关于手机》设备停止》版本号 (多点击它几下,会提示已打开开发者模式)
- 找下手机是否有个 usb调试,打开它
Windows 连接iphone真机
-
确认手机已通过数据线连接电脑
-
确认已安装iTunes,若未安装点击itunes历史版本下载地址, 请下载12.9.4.102之前的版本
win7安装itunes失败说明:https://baijiahao.baidu.com/s?id=1602604904242895792&wfr=spider&for=pc
itunes历史版本下载地址( 请下载12.9.4.102之前的版本):https://mydown.yesky.com/pcsoft/33491427/versions/
- 12.9.4.102 版本会出现以下情况,所以不使用这个版本:
-
12.11.0.26版本itunes连接上,但是HBuilder识别不到;或者itunes连接不上手机
==如果出现上面情况,安装
04-配套软件\itoolssetup_4500.exe
工具,然后手机usb连接电脑,打开 itools 工具,它会自动修复驱动,需要等待10分钟左右。等itools识别到了后,将 HBuilderX重启,就可以识别到了。== -
如果重新安装itunes 识别不到iphone,没有卸载干净,按下面网站卸载
https://zhidao.baidu.com/question/1731993899251396907.html
apple官网提示(我测试无效):https://discussionschinese.apple.com/thread/79226
-
确认iTunes能正常连接手机
-
如手机屏幕弹出需信任本计算机的询问,请同意该授权
如果不小心点了不信任,可请前往“设置”>“通用”>“还原”>“还原位置与隐私”
-
如果是第一次安装完itunes,建议重新启动HBuilderX
-
如果以上方案都无法解决,有可能是因为本地库与iTunes带的库冲突了,一般是iTunes库目录(32位系统目录为:C:\Program Files\Common Files\Apple\Apple Application Support,64位系统目录为:C:\Program Files (x86)\Common Files\Apple\Apple Application Support)下的dll文件和系统库目录(32位系统目录为:C:\WINDOWS\system32,64位系统目录为:C:\Windows\SysWOW64)下的dll重名,可将iTunes库目录下的同名dll文件拷贝到系统库目录下,或者将系统目录下的同名dll文件重命名或删除,然后再重启HBuilder或者重试真机运行
-
有可能是iTunes安装时依赖库丢失,尝试重装iTunes解决问题
-
iTools提供了一个修复驱动的工具和教程,可以参考http://bbs.itools.cn/thread-129390-1-1.html
运行到微信小程序
-
下载微信小程序开发工具稳定版: https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
-
安装微信小程序开发者工具
-
运行到微信小程序,如下
-
如果是第一次使用,需要先配置小程序ide的相关路径,才能运行成功。如下图,需在输入框输入微信开发者工具的安装路径。 若HBuilderX不能正常启动微信开发者工具,需要开发者手动启动,然后将uni-app生成小程序工程的路径拷贝到微信开发者工具里面,在HBuilderX里面开发,在微信开发者工具里面就可看到实时的效果。
微信小程序真机预览
-
访问 https://mp.weixin.qq.com/ 注册微信小程序个人帐号,注册后,再登录如下操作查看AppID
-
打开HBuilderX工具中,项目的
mainfest.json
文件,点击微信小程序 将AppID粘贴进入就可以了, -
打开工具,点击右上角 详情 》基本信息》会有一个AppID框,将上面复制的AppID粘贴即可。
-
点击菜单栏的 预览》自动预览》编译并预览,你打开小程序绑定的微信号,它就会自动运行打开小程序
报错: Cannot read property 'forceUpdate' of undefined
解决:
uni-app 框架与资源路径
uni,读 you ni
,是统一的意思。
不需要专门去学习小程序的语法,uni-app使用的是vue的语法,不是小程序自定义的语法。
学习本套课程需要储备Vue.js全家桶知识,课程地址:
- https://item.taobao.com/item.htm?id=596790926911
- https://ke.qq.com/course/466900
uni-app 官方文档内容说明,根据官方导航栏模块查找知识:
-
搜索框:有疑问直接搜索框输入,BUG直接复制错误提示粘贴上去搜索。
-
介绍:先看这个页面,就知道uniapp大体知识,覆盖了哪些内容,如何进行开发。
-
框架:pages.json 配置项、生命周期、页面通讯、日志打印、定时器。
-
API: 为开发APP、小程序、H5等提供的内置函数。
-
uniCloud: 简化服务端开发,不用自己开发服务端代码。
项目目录及文件介绍
- 一个uni-app项目,默认包含如下目录及文件:
┌─cloudfunctions 云函数目录(阿里云为aliyun,腾讯云为tcb,uniCloud详见 https://uniapp.dcloud.io/uniCloud )
│─components 符合vue组件规范的uni-app组件目录
│ └─comp-a.vue 可复用的a组件
├─hybrid 存放本地网页的目录,详见 https://uniapp.dcloud.net.cn/component/web-view
├─platforms 存放各平台专用页面的目录,详见 https://uniapp.dcloud.net.cn/platform?id=整体目录条件编译
├─pages 业务页面文件存放的目录
│ ├─index
│ │ └─index.vue index页面
│ └─list
│ └─list.vue list页面
├─static 存放应用引用静态资源(如图片、视频等)的目录,注意:静态资源只能存放于此
├─wxcomponents 存放小程序组件的目录,详见 https://uniapp.dcloud.net.cn/frame?id=小程序组件支持
├─main.js Vue初始化入口文件
├─App.vue 应用配置,用来配置App全局样式以及监听、应用生命周期,
详见 https://uniapp.dcloud.net.cn/frame?id=应用生命周期
├─manifest.json 配置应用名称、appid、logo、版本等打包信息,
└─pages.json 配置页面路由、导航条、选项卡等页面类信息,
详见 https://uniapp.dcloud.net.cn/collocation/pages
注意
- 编译到任意平台时,
static
目录下的文件均会被打包进去,非static
目录下的文件(vue、js、css 等)被引用到才会被包含进去。 static
目录下的js
文件不会被编译,如果里面有es6
的代码,不经过转换直接运行,在手机设备上会报错。css
、less/scss
等资源同样不要放在static
目录下,建议这些公用的资源放在common
目录下。
总结
- ==static 目录放图片、视频资源。common目录放
js
、css
、less/scss
等资源,components 目录放可复用vue组件==
资源路径说明
vue组件中引入静态资源
说明
-
template
内引入静态资源,如image
、video
等标签的src
属性时,可以使用相对路径或者绝对路径,形式如下<!-- 绝对路径,/static指根目录下的static目录,在cli项目中/static指src目录下的static目录 --> <image class="logo" src="/static/logo.png"></image> <image class="logo" src="@/static/logo.png"></image> <!-- 相对路径 --> <image class="logo" src="../../static/logo.png"></image>
注意
@
开头的绝对路径以及相对路径会经过base64转换规则校验- 引入的静态资源在非h5平台,均不转为base64。
- H5平台,小于4kb的资源会被转换成base64,其余不转。
- 支付宝小程序组件内 image 标签不可使用相对路径
==总结==
- 因为支付宝小程序使用 image 时不可使用相对路径,所以项目中==全部使用绝对路径,推荐以 @ 开头,==原因看下面js文件。
js文件引入
说明
-
js
文件或script
标签内(包括renderjs等)引入js
文件时,可以使用相对路径和绝对路径,形式如下// 绝对路径,@指向项目根目录,在cli项目中@指向src目录 import add from '@/common/add.js' // 相对路径 import add from '../../common/add.js'
注意
- js文件不支持使用
/
开头的方式引入
==总结==
-
模板中的标签属性在引入图片、视频资源时,使用以
@
开头的绝对路径;而引入js文件时不能使用
/
开头的方式,所以项目中==全部使用绝对路径,推荐以 @ 开头==
css引入静态资源
说明
-
css
文件或style标签
内引入css
文件时(scss、less文件同理),可以使用相对路径或绝对路径/* 绝对路径 */ @import url('/common/uni.css'); @import url('@/common/uni.css'); /* 相对路径 */ @import url('../../common/uni.css');
注意
- 自
HBuilderX 2.6.6-alpha
起支持绝对路径引入静态资源,旧版本不支持此方式
说明
css
文件或style标签
内引用的图片路径可以使用相对路径也可以使用绝对路径,- 需要注意的是,有些小程序端css文件不允许引用本地文件(请看注意事项)。
/* 绝对路径 */
background-image: url(/static/logo.png);
background-image: url(@/static/logo.png);
/* 相对路径 */
background-image: url(../../static/logo.png);
注意
- 引入字体图标请参考,字体图标
@
开头的绝对路径以及相对路径会经过base64转换规则校验- 不支持本地图片的平台,小于40kb,一定会转base64。(共四个平台mp-weixin, mp-qq, mp-toutiao, app v2)
- h5平台,小于4kb会转base64,超出4kb时不转。其余平台不会转base64
总结
- 推荐项目中==全部使用绝对路径,推荐以 @ 开头==,原因见上面2节总结。
==大总结==
-
==在项目开发时,引用任意类型资源文件,全部使用以
@
开头的绝对路径方式引入。原因见上面3节==注意:引入字体图标文件时,使用
~@
开头,如~@/static/icon/iconfont.ttf
iconfont 字体图标
下载图标库
-
进入阿里巴巴矢量图标库https://www.iconfont.cn/,添加图标到项目,然后下载至本地
-
下载解压后的本地文件如下:
- 把 iconfont.css 和 iconfont.ttf 文件拷贝到 /static/icon/ 目录下
-
修改 iconfont.css (Hbuilder 工具取消自动换行(视图》自动换行),不管多长都在一行显示)
修改后如下图,注意 src 最后加上个分号
vue 文件引用字体图标
方式一:Unicode 引用步骤
Unicode 是字体在网页端最原始的应用方式,特点是:
- 兼容性最好,支持 IE6+,及所有现代浏览器。
- 支持按字体的方式去动态调整图标大小,颜色等等。
- 但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。
- 多色有需求建议使用 symbol 的引用方式
-
在 App.vue 文件的
<style>
标签下完成 引用 .ttf 字体文件 和 定义 iconfont 的样式字体文件的引用路径推荐使用以 ==~@== 开头的绝对路径。
网络路径必须加协议头
https
。<style> /* 1. 引用 .ttf 字体文件 */ @font-face { font-family: 'iconfont'; /* 本地方式 */ /*src: url('~@/static/icon/iconfont.ttf') format('truetype'); */ /*小程序只支持网络链接,不要少了https: */ src: url('https://at.alicdn.com/t/font_2116121_4hwc792r6yl.ttf') format('truetype'); } /* 2. 定义 iconfont 的样式 */ .iconfont { font-family: iconfont; /* iconfont 对应上面 font-family 的值, */ } </style>
阿里
Unicode
在线图标链接复制如下(一定不要忘记加 ==https://==): -
挑选相应图标并获取字体编码,应用于页面
注意:类名是
iconfont
,字体编码&#
开头;
结尾<text class="iconfont"></text>
方式二:Font-class 类名引用步骤(推荐方式)
font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。
与 Unicode 使用方式相比,具有如下特点:
- 兼容性良好,支持 IE8+,及所有现代浏览器。
- 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
- 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
- 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
-
在 App.vue 文件的
<style>
标签下使用 import 导入iconfont.css
字体文件把上面方式一的代码注释掉,避免相互影响
注意:font-class类名方式,微信小程序开发工具上不支持网络链接,只支持本地方式;打包上线时,只支持在线方式
<style> /* 本地方式 */ @import url("~@/static/icon/iconfont.css"); /* 微信小程序开发工具上,不支持网络链接,只支持本地方式 打包上线时,只支持在线方式 */ /* @import url("https://at.alicdn.com/t/font_2116121_4hwc792r6yl.css");*/ </style>
阿里
Font class
在线图标链接复制如下(一定不要忘记加 ==https://==)微信小程序不支持网络链接,只支持本地方式: -
挑选相应图标并获取类名,应用于 .vue 页面
注意:
iconfont
和icon-haoping
是iconfont.css
文件声明的,icon-haoping
是具体的图标类名<text class="iconfont icon-haoping"></text>
当前使用 font-class 方式引入字体图标后,也可以采用Unicode字符编码方式使用图标。
<text class="iconfont"></text>
nvue 文件引用字体图标
说明
-
nvue 要使用 Unicode 引用。
-
nvue
文件中不可直接使用css的方式引入字体文件,需要在每个nvue文件中使用js的方式引入。无法App.vue全局引入。 -
nvue
内不支持本地路径引入字体,请==使用网络链接或者base64
形式。==
步骤
-
比如在 video.nvue 文件要使用字体图标,那在此组件的
beforeCreate
生命钩子加载iconfont.ttf
文件。注意:==
src
属性的url
的括号内一定要使用单引号
将链接地址引起来。==<script> export default { beforeCreate() { // #ifdef APP-NVUE // nvue文件 加载unicode图标文件, const dom = weex.requireModule('dom'); dom.addRule('fontFace', { fontFamily: 'iconfont', // 在style中声明 .ionfont 样式引用 // 使用 https:// 开头的网络链接,且用一定要用单引号''引起来 src: "url('https://at.alicdn.com/t/font_2116121_4hwc792r6yl.ttf')" }); // #endif }, } </script>
-
在
style
中声明.iconfont
引用上面加载的字体文件,定义图标大小和颜色。注意:==下面
font-family
的值对应上面 js 中的fontFamily
值。==<style> /* 针对 nvue 文件中使用字体图标,导入Unicode文件 iconfont.ttf, 使用 <text class="iconfont"></text> */ .iconfont { font-family: iconfont; /* iconfont 对应上面 fontFamily 的值, */ font-size: 50rpx; color: #FFFFFF; } </style>
-
挑选相应图标并获取字体编码,应用于 .nvue 页面
注意:类名是
iconfont
,字体编码&#
开头;
结尾<text class="iconfont"></text>
彩色图标 iconfont
-
进入阿里巴巴矢量图标库https://www.iconfont.cn/,添加图标到项目,然后下载至本地
解压后的本地文件如下,核心的是 iconfont.eot 文件。
-
打开电脑命令行,执行以下命令,全局安装 iconfont-tools 转换工具
npm install -g iconfont-tools
-
执行cd命令进入第1步解压后的文件夹后,再执行如命令,然后回车
iconfont-tools
回车后,根据提示输入对应的值,与下图保持一致,后面需要使用:
-
执行完后,就会多出来一个
iconfont-app
的文件夹 -
进入
iconfont-app
文件夹,将其中的iconfont-app-icon.css
复制到项目的/static/icon/
目录下 -
然后在 App.vue 引入该文件
<style> /* 彩色的图标*/ @import url("~@/static/icon/iconfont-weapp-icon.css"); </style>
-
使用:其中
mxg-icon
开头是必须的<text class="mxg-icon mxg-icon-list-color"></text>
-
彩色图标当前对 vue文件有效,控制台会关于 backgroud 的相关警告,可忽略它
==大总结==
关于字体图标大总结:
-
vue 文件中使用Font-class类名方式,统一在
App.vue
中引入iconfont.css图标文件,特别强调:目前微信小程序开发工具不支持网络链接,只支持本地方式;打包上线时,只支持在线方式
<style > /* 每个页面公共css */ /* font-class引入时,微信小程序开发工具不支持网络链接,只支持本地方式;打包上线时,只支持在线方式 */ @import url("~@/static/icon/iconfont.css"); /* 彩色的图标 */ @import url("~@/static/icon/iconfont-app-icon.css"); </style>
模板中使用:
<text class="iconfont icon-haoping"></text>
-
nvue 文件使用Unicode字符编码方式,在每个要使用图标的
.nvue
文件中分别引入iconfont.ttf图标文件,-
引入方式具体参见上面
nvue 文件引用字体图标
-
模板中使用:
<text class="iconfont"></text>
-
框架配置项 pages.json
参考:https://uniapp.dcloud.io/collocation/pages
pages.json
文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。
globalStyle 全局配置
用于设置应用的状态栏、导航条、标题、窗口背景色等。下面配置项默认应用于每个页面。
==注意:更改 pages.json 里面的配置信息后,最好是重新运行项目,并且手机上的app也要退出重新打开;不然有时候不生效。==
状态栏和导航栏
属性 | 类型 | 默认值 | 描述 | 平台差异说明 |
---|---|---|---|---|
navigationBarBackgroundColor | HexColor | #F7F7F7 | 导航栏背景颜色(同状态栏背景色) | APP与H5为#F7F7F7,小程序平台请参考相应小程序文档 |
navigationBarTextStyle | String | white | 导航栏标题颜色及状态栏前景颜色,仅支持 black/white | |
navigationBarTitleText | String | 导航栏标题文字内容 | ||
titleImage | String | 导航栏图片地址(替换导航栏标题文字),支付宝小程序内必须使用https的图片链接地址 | 支付宝小程序、H5、APP | |
transparentTitle | String | none | 导航栏整体透明( always 一直透明 / auto 滑动自适应 / none 不透明)。 测试:在index.vue中来个v-for循环内容超过屏高 | 支付宝小程序、H5、APP |
navigationStyle | String | default | 导航栏样式,仅支持 default/custom, custom不显示原生导航栏并且状态栏不占位,需看使用注意 | 微信小程序 7.0+、百度小程序、H5、App(2.0.3+) |
注意
- 支付宝小程序使用
titleImage
时必须使用https
的图片链接地址,需要真机调试才能看到效果,支付宝开发者工具内无效果 globalStyle
中设置的titleImage
也会覆盖掉pages
->style
内的设置文字标题
参考配置如下:
"globalStyle": {
// 状态栏与导航栏背景色
"navigationBarBackgroundColor": "#FFFFFF",
// 状态栏与导航栏字体颜色,仅支持 black/white(默认)
"navigationBarTextStyle": "black",
// 导航栏标题文字
"navigationBarTitleText": "梦学谷",
// 导航栏图片地址(替换导航栏标题文字)
"titleImage": "/static/logo.png",
// 导航栏整体透明( always 一直透明 / auto 滑动自适应 / none 不透明)
"transparentTitle": "auto"
// 导航栏样式,仅支持 default/custom, custom不显示原生导航栏,状态栏也不占位
// "navigationStyle": "default"
}
bounce 下拉下拉回弹
平台差异官方未更新,老师测试了下面是黄色部分也是可以的
属性 | 类型 | 默认值 | 描述 | 平台差异说明 |
---|---|---|---|---|
backgroundColor | HexColor | #ffffff | 下拉下拉显示出来的窗口的背景色(==如果设置了下面两个,这个就失效了==) | ==IOS/真机==微信小程序 |
backgroundColorTop | HexColor | #ffffff | 下拉顶部窗口的背景色(bounce回弹区域) | iOS/==真机微信小程序== |
backgroundColorBottom | HexColor | #ffffff | 上拉底部窗口的背景色(bounce回弹区域) | IOS/==真机微信小程序== |
参考配置如下:
"globalStyle": {
// ...
// 上拉下拉回弹背景色(ios和真机微小程序)
"backgroundColor": "#e42863",
// 下拉顶部回弹背景色(ios和真机微小程序)
"backgroundColorTop": "#000",
// 上拉底部回弹背景色(ios和真机微小程序)
"backgroundColorBottom": "#345DC2"
}
下拉刷新和上拉触底
主要用于下拉刷新数据,上拉触底查询下一页数据。一般针对需要使用的页面进行配置,而不会全局配置。
属性 | 类型 | 默认值 | 描述 | 平台差异说明 |
---|---|---|---|---|
enablePullDownRefresh | Boolean | false | 是否开启下拉刷新,详见页面生命周期。 | |
backgroundTextStyle | String | dark | 开启下拉刷新后,下拉 loading 的样式,仅支持 dark / light | 微信小程序 |
onReachBottomDistance | Number | 50 | 页面上拉触底事件触发时距页面底部距离,单位只支持px,详见页面生命周期 |
pages 页面配置
参考:https://uniapp.dcloud.net.cn/collocation/pages?id=pages
uni-app
通过 pages 节点配置应用由哪些页面组成,pages 节点接收一个数组,数组每个项都是一个对象,其属性值如下:
属性 | 类型 | 描述 |
---|---|---|
path | String | 配置页面路径 |
style | Object | 配置页面窗口表现,配置项参考 style |
Tips:
- pages节点的第一项为应用入口页(即首页)
- 应用中新增/减少页面,都需要对 pages 数组进行修改
- 文件名不需要写后缀,框架会自动寻找路径下的页面资源
代码示例:
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarBackgroundColor":"#345DC2", // 导航栏背景色
"navigationBarTextStyle":"white", // 导航栏和状态栏字体颜色,仅支持 black/white
"navigationBarTitleText": "首页", // 导航栏标题文字
"app-plus": {
"bounce": "none", // 关闭回弹
"titleNView": { // 自定义导航配置
"type": "transparent", // 滚动透明渐变
"searchInput": { // 原生导航搜索框
"align":"center" ,// 居中
"backgroundColor":"#F0F1F2",
"borderRadius": "30rpx",
"placeholder": "搜索你想要的内容",
"placeholderColor":"#979C9D", // 提示文本颜色
"disabled": true // 禁止输入,点击跳转到搜索页
},
"buttons": [ // 按钮,注意是数组,中括号[]
{
"fontSrc": "/static/icon/iconfont.ttf", // 指定图标文件
"text": "\ue689", // /u 开头,后面 e开始
"fontSize":"23" ,// 按钮大小
"background": "rgba(0,0,0,0)" // 按钮全透明背景
}
]
}
}
}
},
{
"path" : "pages/category/category",
"style" : {
"navigationBarTitleText": "分类"
}
},
{
"path" : "pages/article/article",
"style" : {
"navigationBarTitleText": "阅读"
}
},
{
"path" : "pages/question/question",
"style" : {
"navigationBarTitleText": "问答"
}
},
{
"path" : "pages/my/my",
"style" : {
"navigationBarTitleText": "我的"
}
}
]
}
tabBar 标签导航配置
参考:https://uniapp.dcloud.net.cn/collocation/pages?id=tabbar
代码示例
{
"globalStyle": { // 默认页面配置
},
"pages": [ // 页面配置
],
"tabBar": { // 标签导航配置
"color": "#b0abb3", // 未选中字体颜色
"selectedColor":"#345dc2", // 选中字体颜色
"backgroundColor":"#F8F8F8", // 背景色
"borderStyle":"white", // 边框色
"fontSize":"11px", //字体大小
"height": "52px", //标签栏高度
"list": [
{
"text":"首页", // 标签名
"pagePath":"pages/index/index", // 页面路径
"iconPath":"static/tab/index.png", // 未选中图标
"selectedIconPath":"static/tab/index-active.png" //选中图标
},
{
"text":"分类",
"pagePath":"pages/category/category",
"iconPath":"static/tab/category.png",
"selectedIconPath":"static/tab/category-active.png"
},
{
"text": "阅读",
"pagePath":"pages/article/article",
"iconPath":"static/tab/article.png",
"selectedIconPath":"static/tab/article-active.png"
},
{
"text":"问答",
"pagePath":"pages/question/question",
"iconPath":"static/tab/question.png",
"selectedIconPath":"static/tab/question-active.png"
},
{
"text":"我的",
"pagePath":"pages/my/my",
"iconPath":"static/tab/my.png",
"selectedIconPath":"static/tab/my-active.png"
}
]
},
}
路由与页面跳转
路由
uni-app
页面路由为框架统一管理,开发者需要在pages.json里配置每个路由页面的路径及页面样式。所以 uni-app
的路由用法与 Vue Router
不同,如仍希望采用 Vue Router
方式管理路由,可在插件市场搜索 Vue-Router。
路由跳转
uni-app
有两种页面路由跳转方式:调用API跳转、navigator组件跳转。
调用API跳转
参考:https://uniapp.dcloud.io/api/router?id=navigateto
-
uni.navigateBack(Object)
: 保留当前页面,跳转到应用内的某个页面,使用uni.navigateBack
可以返回到原页面。注意:
- 跳转到 tabBar 页面只能使用 switchTab 跳转
// 1. 页面跳转,带参数 uni.navigateTo({ url: '/pages/auth/login?id=1&name=meng', // 目标页面,注意:页面要在 pages.json 的 pages 数组中配置了 animationType: "slide-in-bottom", // 打开页面动画,仅App支持。当前 从下往上 打开 animationDuration: 300, // 窗口动画持续时间,单位为 ms, 默认300ms }) // login.vue 页面接收参数 export default { onLoad(option) { //option为object类型,会序列化上个页面传递的参数 console.log(option.id); //打印出上个页面传递的参数。 console.log(option.name); //打印出上个页面传递的参数。 }, } // 2. 传递对象时,转JSON字符串 const params = {id: 1, name: '梦学谷'} uni.navigateTo({ url: '/pages/auth/login?params=' + JSON.stringify(params) }) // login.vue 页面接收对象参数 onLoad(option) { const params = JSON.parse( option.params ) console.log(params.id, params.name) }, // 3. url有长度限制,太长的字符串会传递失败,使用encodeURIComponent方式解决: const params = {id: 1, name: '梦学谷', desc: 'xxxxxxxxxx'} uni.navigateTo({ url: '/pages/auth/login?params=' + encodeURIComponent(JSON.stringify(params)) }) // login.vue 页面接收参数 onLoad (option) { const params = JSON.parse(decodeURIComponent(option.params)) console.log(params.id, params.name, params.desc) }
-
uni.redirectTo(Object)
: 重定向页面,关闭当前页面,跳转到应用内的某个页面,返回不到原页面。注意:
- 跳转到 tabBar 页面只能使用 switchTab 跳转
<!-- loign.vue --> <button type="default" @click="toOrderPage">我的订单</button> <script> export default { methods: { toOrderPage() { const params = {id: 1, name: '梦学谷'} uni.redirectTo({ // 重定向到目标页面,无法回退到当前页 url: '/pages/order/order?params=' + JSON.stringify(params) }) } } } </script>
<!-- login.vue --> <script> export default { onLoad(option) { const params = JSON.parse( option.params ) console.log(params.id) console.log(params.name) }, } </script>
测试:从 index.vue 进 login.vue ,再重定向到 order.vue 页面,然后点击 order.vue 导航栏后退按钮,回到了 index.vue 页面。
-
uni.reLaunch(Object)
:关闭所有页面,打开到应用内的某个页面。==导航<后退按钮,无法后退。==toOrderPage() { const params = {id: 1, name: '梦学谷'} // uni.redirectTo({ // 重定向到目标页面,无法回退到当前页 uni.reLaunch({ // 关闭所有页面,仅保留此页面:无法后退 url: '/pages/order/order?params=' + JSON.stringify(params) }) }
-
uni.switchTab(Object)
:跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。// index.vue 页面 methods: { // 跳转分类标签页 toCategoryPage() { uni.switchTab({ url: '/pages/category/category' }) } }
-
uni.navigateBack(Object)
:关闭当前页面,返回上一页面或多级页面。uni.navigateBack({ delta: 1 // 返回的页面数, 1后退上一页面 animationType: 'slide-out-bottom', // 后退动画 animationDuration: 300 })
动画注意:
-
窗口的显示/关闭动画效果仅App支持,可作用在:
- API (animationTyp参数)
- navigator 组件(animation-type属性),但是测试 animation-type="slide-in-bottom" 并无动画效果,bug
- pages.json (animationType) 中配置,
- 优先级为:
API == navigator组件 > pages.json
。
动画取值:
显示动画 关闭动画 显示动画描述(==关闭动画与之相反==) slide-in-right slide-out-right 新窗体从右侧进入 slide-in-left slide-out-left 新窗体从左侧进入 slide-in-top slide-out-top 新窗体从顶部进入 slide-in-bottom slide-out-bottom 新窗体从底部进入 pop-in pop-out 新窗体从左侧进入,且老窗体被挤压而出 fade-in fade-out 新窗体从透明到不透明逐渐显示 zoom-out zoom-in 新窗体从小到大缩放显示 zoom-fade-out zoom-fade-in 新窗体从小到大逐渐放大并且从透明到不透明逐渐显示 none none 无动画
navigator 组件跳转
参考:https://uniapp.dcloud.net.cn/component/navigator
使用 navigator
组件类似HTML中的<a>
组件,但只能跳转本地页面。目标页面必须在pages.json中注册。
示例代码
注意动画效果可能无效
<template>
<view>
利用navigator组件跳转:
<navigator :url="'/pages/auth/login?params=' + encodeURIComponent(JSON.stringify({id: 1,name: 'meng'}))"
animation-type="slide-in-bottom">
<button>跳转到-登录页</button>
</navigator>
<navigator url="/pages/order/order" open-type="redirect">
<button>当前页面打开-订单页</button>
</navigator>
<navigator url="/pages/category/category" open-type="switchTab" hover-class="red-hover">
<view>分类tab页</view>
</navigator>
</view>
</template>
<style>
.red-hover {
background-color: #007AFF;
}
</style>
uni-app 生命周期
在 uni-app 中包含了 应用生命周期、页面生命周期、和组件生命周期( Vue.js的)函数。
参考:https://uniapp.dcloud.io/collocation/frame/lifecycle
应用生命周期
uni-app
支持如下应用生命周期函数:
函数名 | 说明 |
---|---|
onLaunch | 当 uni-app 初始化完成时触发(全局只触发一次) |
onShow | 当 uni-app 启动,或从后台进入前台显示 |
onHide | 当 uni-app 从前台进入后台 |
onError | 当 uni-app 报错时触发(在 index.vue 页面的方法中 const i =1; i=2; 报错监听 ) |
页面不存在监听函数==(目前uni.navigateTo({url: '/pages/course/course'})没有的页面跳转,测试无效)== |
注意:==应用生命周期仅可在App.vue
中监听,在其它页面监听无效。==
示例代码
<!-- App.vue -->
<script>
export default {
onLaunch() {
console.log('应用初始化完成,全局触发一次')
},
onShow() {
console.log('应用从后台进入前台,多次')
},
onHide() {
console.log('应用从前台进入后台,多次')
},
onError(err) {
console.log('监听页面异常', err)
},
}
</script>
<!-- index.vue -->
<template>
<view >
<button type="default" @click="navTo">课程详情页</button>
</view>
</template>
<script>
export default {
methods: {
navTo() {
const i = 1
i = 2 // 报错, onError可监听到
//uni.navigateTo({url: '/pages/course/course'}) // 不存在,无法监听
}
}
}
</script>
页面生命周期
uni-app
支持如下页面生命周期函数:
-
在 pages.json中配置的页面才有以下函数,子组件中没有这些函数
函数名 说明 平台差异说明 最低版本 onLoad 监听页面加载,其参数为上个页面传递的数据,参数类型为Object(用于页面传参),参考示例 onShow 监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面 onReady 监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发 onHide 监听页面隐藏
组件生命周期
uni-app
组件支持的生命周期,与vue标准组件的生命周期相同。这里没有页面级的onLoad等生命周期:
==注意:一般在子组件使用,当然页面中也是可以使用的。==
函数名 | 说明 | 平台差异说明 | 最低版本 |
---|---|---|---|
beforeCreate | 在实例初始化之后被调用。详见 | ||
created | 在实例创建完成后被立即调用。详见 | ||
beforeMount | 在挂载开始之前被调用。详见 | ||
mounted | 挂载到实例上去之后调用。详见 注意:此处并不能确定子组件被全部挂载,如果需要子组件完全挂载之后在执行操作可以使用$nextTick Vue官方文档 |
||
beforeUpdate | 数据更新时调用,发生在虚拟 DOM 打补丁之前。详见 | 仅H5平台支持 | |
updated | 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。详见 | 仅H5平台支持 | |
beforeDestroy | 实例销毁之前调用。在这一步,实例仍然完全可用。详见 | ||
destroyed | Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。详见 |
运行环境判断和解决跨端兼容性
参考:https://uniapp.dcloud.net.cn/frame?id=运行环境判断
开发环境和生产环境
uni-app
可通过 process.env.NODE_ENV
判断当前环境是开发环境还是生产环境。一般用于连接测试服务器或生产服务器的动态切换。
- 在 HBuilderX 中,点击“运行”编译出来的代码是开发环境,点击“发行”编译出来的代码是生产环境
if(process.env.NODE_ENV === 'development'){
console.log('开发环境')
}else{
console.log('生产环境')
}
跨端兼容
uni-app 已将常用的组件、JS API 封装到框架中,开发者按照 uni-app 规范开发即可保证多平台兼容,大部分业务均可直接满足。
但每个平台有自己的一些特性,因此会存在一些无法跨平台的情况。
- 大量写 if else,会造成代码执行性能低下和管理混乱。
- 编译到不同的工程后二次修改,会让后续升级变的很麻烦。
在 C 语言中,通过 #ifdef、#ifndef 的方式,为 windows、mac 等不同 os 编译不同的代码。 uni-app
参考这个思路,为 uni-app
提供了条件编译手段,在一个工程里优雅的完成了平台个性化实现。
条件编译-解决跨端兼容性
平台判断有2种场景,一种是在编译期判断(条件编译),一种是在运行期判断。
条件编译语法
-
条件编译:是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。
-
写法:==以 #ifdef 或 #ifndef 加 %PLATFORM% 开头,以 #endif 结尾。==
-
#ifdef
:if defined 仅在某平台存在 -
#ifndef
:if not defined 除了某平台均存在 -
%PLATFORM%:平台名称,可取值如下:
值 平台 APP-PLUS App APP-PLUS-NVUE或APP-NVUE App nvue H5 H5 MP-WEIXIN 微信小程序 MP-ALIPAY 支付宝小程序 MP-BAIDU 百度小程序 MP-TOUTIAO 字节跳动小程序 MP-QQ QQ小程序 MP-360 360小程序 MP 微信小程序/支付宝小程序/百度小程序/字节跳动小程序/QQ小程序/360小程序 QUICKAPP-WEBVIEW 快应用通用(包含联盟、华为) QUICKAPP-WEBVIEW-UNION 快应用联盟 QUICKAPP-WEBVIEW-HUAWEI 快应用华为 -
-
示例说明
条件编译写法 说明 #ifdef APP-PLUS 需条件编译的代码 #endif 仅出现在 App 平台下的代码 #ifndef H5 需条件编译的代码 #endif 除了 H5 平台,其它平台均存在的代码 #ifdef H5 || MP-WEIXIN 需条件编译的代码 #endif 在 H5 平台或微信小程序平台存在的代码(这里只有||,不可能出现&&,因为没有交集) -
支持的文件
- .vue
- .js
- .css
- pages.json
- 各预编译语言文件,如:.scss、.less、.stylus、.ts、.pug
-
注意:
- 条件编译是利用注释实现的,在不同语法里注释写法不一样,js使用
// 注释
、==css 使用/* 注释 */
==、vue/nvue 模板里使用<!-- 注释 -->
- 条件编译 APP-PLUS 包含 APP-NVUE 和 APP-VUE,APP-PLUS-NVUE和APP-NVUE没什么区别,为了简写后面出了APP-NVUE ;
- 条件编译是利用注释实现的,在不同语法里注释写法不一样,js使用
组件(模板)的条件编译
<!-- #ifdef %PLATFORM% -->
平台特有的组件
<!-- #endif -->
示例:
<template>
<view>
<!-- #ifdef APP-PLUS -->
<view>APP中显示</view>
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<view>不在APP中显示</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN || H5 -->
<!-- 还支持多平台同时编译,使用 || 来分隔平台名称 -->
<view>在微信小程序或H5端显示_点击下载APP</view>
<!-- #endif -->
</view>
</template>
API(js)的条件编译
// #ifdef %PLATFORM%
平台特有的API实现
// #endif
示例:
<script>
export default {
data() {
return {
// #ifdef APP-PLUS
title: '我是APP端',
// #endif
}
},
methods: {
test1() {
// #ifdef H5
console.log('兼容H5平台')
// #endif
}
}
}
</script>
样式 (style)的条件编译
/* #ifdef %PLATFORM% */
平台特有样式
/* #endif */
注意: 样式的条件编译,==无论是 css 还是 sass/scss/less/stylus 等预编译语言中,必须使用 /*注释*/
的写法。==
正确写法:
<style lang="scss">
.content {
/* #ifdef MP */
color: red;
/* #endif */
}
</style>
==错误写法:==
<style lang="scss">
.content {
// #ifdef MP 错误的写法,不能用 //,而是用 /**/
color: red;
// #endif
}
</style>
pages.json 的条件编译
下面的页面,只有运行至 App 时才会编译进去。
不同平台下的特有功能,以及小程序平台的分包,都可以通过 pages.json 的条件编译来更好地实现。这样,就不会在其它平台产生多余的资源,进而减小包体积。
static 目录的条件编译
在不同平台,引用的静态资源可能也存在差异,通过 static 的的条件编译可以解决此问题,static 目录下新建不同平台的专有目录(目录名称同 %PLATFORM%
值域,但字母均为小写),专有目录下的静态资源只有在特定平台才会编译进去。
如以下目录结构,a.png
只有在微信小程序平台才会编译进去,b.png
在所有平台都会被编译。
┌─static
│ ├─mp-weixin
│ │ └─a.png
│ └─b.png
├─main.js
├─App.vue
├─manifest.json
└─pages.json
运行期判断IOS/Android平台
Android 和 iOS 平台不支持通过条件编译来区分,如果需要区分 Android、iOS 平台,请通过调用 uni.getSystemInfo 来获取平台信息。
-
运行期判断 运行期判断是指代码已经打入包中,仍然需要在运行期判断平台,此时可使用
uni.getSystemInfoSync().platform
判断客户端环境是 Android、iOS 还是小程序开发工具(在百度小程序开发工具、微信小程序开发工具、支付宝小程序开发工具中使用uni.getSystemInfoSync().platform
返回值均为 devtools)。switch(uni.getSystemInfoSync().platform){ case 'android': console.log('运行Android上') break; case 'ios': console.log('运行iOS上') break; default: console.log('运行在开发者工具上') break; }
如有必要,也可以在条件编译里自己定义一个变量,赋不同值。在后续运行代码中动态判断环境。
-
判断是否为: IOS 平台的APP端
<template> <view> <view v-if="isIosApp"> 是IOS平台的APP端 </view> <view v-else> 不是IOS平台的APP端 </view> </view> </template> <script> export default { data() { return { isIosApp: false, // 是否为 IOS平台的APP端 } }, onLoad() { // #ifdef APP-PLUS this.isIosApp = uni.getSystemInfoSync().platform === 'ios' // #endif }, } </script>
页面样式和布局和nvue教程
参考:https://uniapp.dcloud.net.cn/frame?id=页面样式与布局
尺寸单位
uni-app
支持的通用 css 单位包括 px、rpx
- px 即屏幕像素
- rpx 即响应式px,一种根据屏幕宽度自适应的动态单位。以750宽的屏幕为基准,750rpx恰好为屏幕宽度。屏幕变宽,rpx 实际显示效果会等比放大。但在 App 端和 H5 端屏幕宽度达到 960px 时,默认将按照 375px 的屏幕宽度进行计算,具体配置参考:rpx计算配置
- 可以使用
uni.upx2px()
将 rpx 大小转为 px 大小。
下面对 rpx
详细说明:
设计师在提供设计图时,一般只提供一个分辨率的图。
严格按设计图标注的 px 做开发,在不同宽度的手机上界面很容易变形。
而且主要是宽度变形。高度一般因为有滚动条,不容易出问题。由此,引发了较强的动态宽度单位需求。
微信小程序设计了 rpx 解决这个问题。uni-app
在 App 端、H5 端都支持了 rpx
,并且可以配置不同屏幕宽度的计算方式,具体参考:rpx计算配置。
rpx 是相对于基准宽度的单位,可以根据屏幕宽度进行自适应。uni-app
规定屏幕基准宽度 750rpx。
开发者可以通过设计稿基准宽度计算页面元素 rpx 值,设计稿 1px 与框架样式 1rpx 转换公式如下:
设计稿 1px / 设计稿基准宽度 = 框架样式 1rpx / 750rpx
换言之,页面元素宽度在 uni-app
中的宽度计算公式:
750 * 元素在设计稿中的宽度 / 设计稿基准宽度
举例说明:
- 若设计稿宽度为 750px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在
uni-app
里面的宽度应该设为:750 * 100 / 750
,结果为:100rpx。 - 若设计稿宽度为 640px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在
uni-app
里面的宽度应该设为:750 * 100 / 640
,结果为:117rpx。 - 若设计稿宽度为 375px,元素 B 在设计稿上的宽度为 200px,那么元素 B 在
uni-app
里面的宽度应该设为:750 * 200 / 375
,结果为:400rpx。
全局样式与局部样式
定义在 App.vue 中的样式为全局样式,作用于每一个页面。
在 pages 目录下 的 vue 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 App.vue 中相同的选择器。
注意:
-
App.vue 中通过
@import
语句可以导入外联样式文件,一样作用于每一个页面。<style> /*每个页面公共css */ @import url("/common/css/common.css"); </style>
CSS变量
uni-app 提供内置 CSS 变量
CSS变量 | 描述 | App | 小程序 | H5 |
---|---|---|---|---|
--status-bar-height | 系统状态栏高度 | 系统状态栏高度、nvue注意见下 | 25px | 0 |
--window-top | 内容区域距离顶部的距离 | 0 | 0 | NavigationBar 的高度 |
--window-bottom | 内容区域距离底部的距离 | 0 | 0 | TabBar 的高度 |
注意:
var(--status-bar-height)
此变量在微信小程序环境为固定25px
,在 App 里为手机实际状态栏高度。- 当设置
"navigationStyle":"custom"
取消原生导航栏后,由于窗体为沉浸式,占据了状态栏位置。此时可以使用一个高度为var(--status-bar-height)
的 view 放在页面顶部,避免页面内容出现在状态栏。 - 由于在H5端,不存在原生导航栏和tabbar,也是前端div模拟。如果设置了一个固定位置的居底view,在小程序和App端是在tabbar上方,但在H5端会与tabbar重叠。此时可使用
--window-bottom
,不管在哪个端,都是固定在tabbar上方。 - 目前 nvue 在App端,还不支持
--status-bar-height
变量,替代方案是在页面onLoad时通过uni.getSystemInfoSync().statusBarHeight获取状态栏高度,然后通过style绑定方式给占位view设定高度。下方提供了示例代码
<template>
<view>
<view class="status_bar">
<!-- 这里是状态栏 -->
</view>
<view> 状态栏下的文字 </view>
</view>
</template>
<style>
.status_bar {
height: var(--status-bar-height);
width: 100%;
}
</style>
固定值
uni-app
中以下组件的高度是固定的,不可修改:
组件 | 描述 | App | H5 |
---|---|---|---|
NavigationBar | 导航栏 | 44px | 44px |
TabBar | 底部选项卡 | HBuilderX 2.3.4之前为56px,2.3.4起和H5调为一致,统一为 50px。但可以自主更改高度) | 50px |
各小程序平台,包括同小程序平台的iOS和Android的高度也不一样。
<template/>
和 <block/>
参考:https://uniapp.dcloud.net.cn/frame?id=template-block
uni-app
支持在 template 模板中嵌套 <template/>
和 <block/>
,用来进行 列表渲染 和 条件渲染。
<template/>
和 <block/>
并不是一个组件,它们仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。
<block/>
在不同的平台表现存在一定差异,==推荐统一使用 <template/>
==。
代码示例
<template>
<view>
<template v-if="test">
<view>test 为 true 时显示</view>
</template>
<template v-else>
<view>test 为 false 时显示</view>
</template>
</view>
</template>
<script>
export default {
data() {
return {
test: false,
}
},
</script>
Flex布局
为兼容多端跨平台运行,建议使用flex布局进行开发,关于Flex布局可以参考外部文档A Complete Guide to Flexbox、阮一峰的flex教程等。
nvue 教程
参见:https://uniapp.dcloud.net.cn/nvue-outline
nvue是属于 weex 编写范畴,作用是增强uniapp对原生渲染支持
nvue的组件和API写法与vue页面一致,其内置组件还比vue页面内置组件增加了更多,详见。
nvue开发与vue开发的常见区别
基于原生引擎的渲染,虽然还是前端技术栈,但和web开发肯定是有区别的。
- nvue 页面控制显隐只可以使用
v-if
不可以使用v-show
- nvue 页面只能使用
flex
布局,不支持其他布局方式。页面开发前,首先想清楚这个页面的纵向内容有什么,哪些是要滚动的,然后每个纵向内容的横轴排布有什么,按 flex 布局设计好界面。 - nvue 页面的布局排列方向默认为竖排(
column
),如需改变布局方向,可以在manifest.json
->app-plus
->nvue
->flex-direction
节点下修改,仅在 uni-app 模式下生效。详情。 - nvue页面编译为H5、小程序时,会做一件css默认值对齐的工作。因为weex渲染引擎只支持flex,并且默认flex方向是垂直。而H5和小程序端,使用web渲染,默认不是flex,并且设置
display:flex
后,它的flex方向默认是水平而不是垂直的。所以nvue编译为H5、小程序时,会自动把页面默认布局设为flex、方向为垂直。当然开发者手动设置后会覆盖默认设置。 - 文字内容,必须、只能在
<text>
组件下。不能在<div>
、<view>
的text
区域里直接写文字。否则即使渲染了,也无法绑定js里的变量。 - 只有
text
标签可以设置字体大小,字体颜色。 - 布局不能使用百分比、没有媒体查询。
- nvue 切换横竖屏时可能导致样式出现问题,建议有 nvue 的页面锁定手机方向。
- 支持的css有限,不过并不影响布局出你需要的界面,
flex
还是非常强大的。详见 - 不支持背景图。但可以使用
image
组件和层级来实现类似web中的背景效果。因为原生开发本身也没有web这种背景图概念 - css选择器支持的比较少,只能使用 class 选择器。详见
- nvue 的各组件在安卓端默认是透明的,如果不设置
background-color
,可能会导致出现重影的问题。 class
进行绑定时只支持数组语法。- Android端在一个页面内使用大量圆角边框会造成性能问题,尤其是多个角的样式还不一样的话更耗费性能。应避免这类使用。
- nvue页面没有
bounce
回弹效果,只有几个列表组件有bounce
效果,包括list
、recycle-list
、waterfall
。 - 原生开发没有页面滚动的概念,页面内容高过屏幕高度并不会自动滚动,只有部分组件可滚动(
list
、waterfall
、scroll-view/scroller
),要滚得内容需要套在可滚动组件下。这不符合前端开发的习惯,所以在 nvue 编译为 uni-app模式时,给页面外层自动套了一个scroller
,页面内容过高会自动滚动。(组件不会套,页面有recycle-list
时也不会套)。后续会提供配置,可以设置不自动套。 - 在 App.vue 中定义的全局js变量不会在 nvue 页面生效。
globalData
和vuex
是生效的。 - App.vue 中定义的全局css,对nvue和vue页面同时生效。如果全局css中有些css在nvue下不支持,编译时控制台会报警,建议把这些不支持的css包裹在条件编译里,
APP-PLUS-NVUE
- 不能在
style
中引入字体文件,nvue 中字体图标的使用参考:加载自定义字体。如果是本地字体,可以用plus.io
的API转换路径。 - 目前不支持在 nvue 页面使用
typescript/ts
。 - nvue 页面关闭原生导航栏时,想要模拟状态栏,可以参考文章。但是,仍然强烈建议在nvue页面使用原生导航栏。nvue的渲染速度再快,也没有原生导航栏快。原生排版引擎解析
json
绘制原生导航栏耗时很少,而解析nvue的js绘制整个页面的耗时要大的多,尤其在新页面进入动画期间,对于复杂页面,没有原生导航栏会在动画期间产生整个屏幕的白屏或闪屏。
样式
注意事项
- nvue的css仅支持flex布局,是webview的css语法的子集。这是因为操作系统原生排版不支持非flex之外的web布局。当然flex足以排布出各种页面,只是写法需要适应。
- 在选择器方面支持的较少,只支持简单的
class="classA"
。 - class 进行绑定时只支持数组语法。
- 不支持媒体查询
- 不支持复合样式,不支持简写
- 不能在 style 中引入字体文件
- 布局不能使用百分比,如
width:100%
; - 有些web的css属性在nvue里无法支持,比如背景图。但可以使用image组件和层级来实现类似web中的背景效果。因为原生开发本身也没有web这种背景图概念
- nvue 的各组件在安卓端默认是透明的,如果不设置
background-color
,可能会导致出现重影的问题 - 文字内容,必须只能在
text
组件下,text
组件不能换行写内容,否则会出现无法去除的周边空白 - 只有
text
标签可以设置字体大小,字体颜色
nvue 和 vue 相互通讯
https://uniapp.dcloud.io/collocation/frame/communication
uni.$emit(eventName,OBJECT)
触发全局的自定事件。附加参数都会传给监听器回调。
属性 | 类型 | 描述 |
---|---|---|
eventName | String | 事件名 |
OBJECT | Object | 触发事件携带的附加参数 |
代码示例
uni.$emit('update',{msg:'页面更新'})
uni.$on(eventName,callback)
监听全局的自定义事件。事件可以由 uni.$emit 触发,回调函数会接收所有传入事件触发函数的额外参数。
属性 | 类型 | 描述 |
---|---|---|
eventName | String | 事件名 |
callback | Function | 事件的回调函数 |
代码示例
onLoad() {
uni.$on('update',function(data){
console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
})
}
uni.$once(eventName,callback)
监听全局的自定义事件。事件可以由 uni.$emit 触发,但是只触发一次,在第一次触发之后移除监听器。
属性 | 类型 | 描述 |
---|---|---|
eventName | String | 事件名 |
callback | Function | 事件的回调函数 |
代码示例
onLoad() {
uni.$once('update',function(data){
console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
})
}
uni.$off([eventName, callback])
移除全局自定义事件监听器。在 un
属性 | 类型 | 描述 |
---|---|---|
eventName | Array<String> | 事件名 |
callback | Function | 事件的回调函数 |
代码示例
onUnload() {
// 移除 update 监听器
uni.$off('update')
}
Tips
- 如果没有提供参数,则移除所有的事件监听器;
- 如果只提供了事件,则移除该事件所有的监听器;
- 如果同时提供了事件与回调,则只移除这个回调的监听器;
- 提供的回调必须跟$on的回调为同一个才能移除这个回调的监听器;
常用组件
参考:https://uniapp.dcloud.net.cn/component/README
视图容器
view
它类似于传统html中的div,用于包裹各种元素内容。
如果使用nvue,则需注意,包裹文字应该使用text组件 。
属性说明
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
hover-class | String | none | 指定按下去的样式类。当 hover-class="none" 时,没有点击态效果 |
hover-stop-propagation | Boolean | false | 指定是否阻止本节点的祖先节点出现点击态 |
hover-start-time | Number | 50 | 按住后多久出现点击态,单位毫秒 |
hover-stay-time | Number | 400 | 手指松开后点击态保留时间,单位毫秒 |
scroll-view
可滚动视图区域。用于区域滚动。针对一个区域左右、上下滑动
<template>
<view>
<!-- scroll-x 横向滚动,scroll-left 初始加载时横向滚动条位置 -->
<scroll-view class="scroll-view" scroll-y="true" scroll-left="30">
<view>A</view>
<view>B</view>
<view>C</view>
</scroll-view>
</view>
</template>
<style lang="scss">
/* scroll-view 左右滑动 */
.scroll-view {
// 内容一行显示不换行
white-space: nowrap;
view {
// 同一行显示
display: inline-block;
width: 300rpx;
height: 200rpx;
margin-right: 10rpx;
background-color: red;
}
}
</style>
使用竖向滚动时,需要给 <scroll-view>
一个固定高度,通过 css 设置 height。
swiper
滑块视图容器。swiper
是多个区域左右、上下切换。比如banner轮播图。
注意滑动切换和滚动的区别,滑动切换是一屏一屏的切换。swiper下的每个swiper-item是一个滑动切换区域,不能停留在2个滑动区域之间。
<swiper class="swiper" :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000">
<swiper-item>
<view class="swiper-item">图1</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">图2</view>
</swiper-item>
</swiper>
match-media
media query 匹配检测节点。自适应屏幕大小显示和隐藏某区域
类似于网页开发中使用媒体查询来适配大屏小屏,match-media是一个可适配不同屏幕的基本视图组件。可以指定一组 media query 媒体查询规则,满足查询条件时,这个组件才会被展示。
例如:在match-media组件中放置一个侧边栏,媒体查询规则设置为宽屏才显示,就可以实现在PC宽屏显示该侧边栏,而在手机窄屏中不显示侧边栏的效果。
平台兼容性
app | 微信小程序 | 支付宝小程序 | qq小程序 | 百度小程序 | 字节小程序 | 360小程序 | 快应用 |
---|---|---|---|---|---|---|---|
2.8.12+,app-vue | 基础库 2.11.1+ | √ | √ | √ | √ | √ | × |
注意:支付宝小程序、qq小程序、百度小程序、字节小程序,暂不支持监听屏幕动态改变,即只执行一次媒体查询。
属性说明
属性名 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
min-width | number | 否 | 页面最小宽度( px 为单位) | |
max-width | number | 否 | 页面最大宽度( px 为单位) | |
width | number | 否 | 页面宽度==等于==此值时显示( px 为单位) | |
min-height | number | 否 | 页面最小高度( px 为单位) | |
max-height | number | 否 | 页面最大高度( px 为单位) | |
height | number | 否 | 页面高度==等于==此值时显示( px 为单位) | |
orientation | string | 否 | 屏幕方向(纵向 landscape 或 横向portrait ) |
示例代码
<movable-area>
<!-- x和y属性是视图目标x和y坐标位置 -->
<movable-view :x="10" :y="30" direction="all" >text</movable-view>
</movable-area>
<style>
movable-area {
height: 300rpx;
width: 100%;
background-color: #D8D8D8;
overflow: hidden;
}
movable-view {
display: flex;
align-items: center;
justify-content: center;
height: 150rpx;
width: 150rpx;
background-color: #007AFF;
color: #fff;
}
</style>
movable-area 和 movable-view
movable-area
和 movable-view
组件组合使用,实现可拖动区域组件。由于app和小程序的架构是逻辑层与视图层分离。
movable-area
指代可拖动的范围,在其中内嵌movable-view
组件用于指示可拖动的区域。其中movable-view
必须在movable-area
组件中,并且必须是直接子节点,否则不能移动。
即手指/鼠标按住movable-view
拖动或双指缩放,但拖不出movable-area
规定的范围。
当然也可以不拖动,而使用代码来触发movable-view
在movable-area
里的移动缩放。
平台差异说明
App | H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 字节跳动小程序 | QQ小程序 | 快应用 | 360小程序 |
---|---|---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | x | √ | √ | √ |
注意:
-
movable-area 和 movable-view 都必须设置 width 和 height 属性,不设置默认为 10px
-
movable-area app-nvue平台 暂不支持手势缩放,并且和滚动冲突。
-
movable-view 默认为绝对定位,top和left属性为0px
-
当 movable-view 小于movable-area 时,movable-view的移动范围是在movable-area内;当movable-view大于movable-area时,movable-view的移动范围必须包含movable-area(x轴方向和y轴方向分开考虑)
cover-view
覆盖在原生组件上的文本视图。
app-vue和小程序框架,渲染引擎是webview的。但为了优化体验,部分组件如map、video、textarea、canvas通过原生控件实现,原生组件层级高于前端组件(类似flash层级高于div)。为了能正常覆盖原生组件,设计了cover-view。
- app-nvue所有组件均为原生渲染,不存在前端组件无法覆盖原生组件的问题。但为了保持多端兼容,nvue里也实现了
cover-view
,作用于普通view
一样。 - 微信小程序部分原生组件实现了同层渲染,在指定的基础库版本上,某些原生组件可无需使用
cover-view
覆盖,详见 - 字节跳动小程序不需要
cover-view
,因其原生组件均实现了同层渲染。 - 360小程序不存在原生组件,无此概念
示例代码
将 /pages/question/question.==vue== 文件改为 question.==nvue==
<template>
<view>
<video style="width: 750rpx;" src="">
<!-- 位于播放器上层 -->
<cover-view style="color: red;">
<text>播放</text>
</cover-view>
</video>
</view>
</template>
cover-image
覆盖在原生组件上的图片视图。可覆盖的原生组件同cover-view
,支持嵌套在cover-view
里。与 images
组件使用方式一样。
其他组件使用方式参见文档,后面用的时间会讲。
常用 API
数据缓存
参考:https://uniapp.dcloud.net.cn/api/storage/storage?id=setstorage
注意
uni-app的Storage在不同端的实现不同:
- H5端为localStorage,浏览器限制5M大小,是缓存概念,可能会被清理
- App端为原生的plus.storage,无大小限制,不是缓存,是持久化的
- 各个小程序端为其自带的storage api,数据存储生命周期跟小程序本身一致,即除用户主动删除或超过一定时间被自动清理,否则数据都一直可用。
- 微信小程序单个 key 允许存储的最大数据长度为 1MB,所有数据存储上限为 10MB。
- 支付宝小程序单条数据转换成字符串后,字符串长度最大200*1024。同一个支付宝用户,同一个小程序缓存总上限为10MB。
- 百度、字节跳动小程序文档未说明大小限制
除此之外,其他数据存储方案:
相关API
-
uni.setStorage(OBJECT)
将数据存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个异步接口。uni.setStorage({ key: 'storage_key', data: 'hello', success: function () { console.log('success'); } });
-
uni.setStorageSync(KEY,DATA)
将 data 存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个同步接口。uni.setStorageSync('storage_key', 'hello');
-
uni.getStorage(OBJECT)
从本地缓存中异步获取指定 key 对应的内容。uni.getStorage({ key: 'storage_key', success: function (res) { console.log(res.data); } });
-
uni.getStorageSync(KEY)
从本地缓存中同步获取指定 key 对应的内容。const value = uni.getStorageSync('storage_key');
-
uni.removeStorage(OBJECT)
从本地缓存中异步移除指定 key。uni.removeStorage({ key: 'storage_key', success: function (res) { console.log('success'); } });
-
uni.removeStorageSync(KEY)
从本地缓存中同步移除指定 key。uni.removeStorageSync('storage_key');
-
uni.clearStorage()
和uni.clearStorageSync()
都是清理本地数据缓存。uni.clearStorage(); uni.clearStorageSync();