更新记录

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

  1. 什么是 HBuilderX

    HBuilderX,H是HTML的首字母,Builder是构造者,X是HBuilder的下一代版本。我们也简称HXHX轻如编辑器、强如IDE的合体版本,它是免费的。

    1. 轻巧

      仅10余M的绿色发行包(不含插件)

    2. 极速 不管是启动速度、大文档打开速度、编码提示,都极速响应 C++的架构性能远超Java或Electron架构

    3. vue开发强化 HX对vue做了大量优化投入,开发体验远超其他开发工具 详见 按下Alt+鼠标左键可直接打开网址

    4. 小程序支持 国外开发工具没有对中国的小程序开发优化,HX可新建uni-app小程序快应用等项目,为国人提供更高效工具

    5. markdown利器 HX是唯一一个新建文件默认类型是markdown的编辑器,也是对md支持最强的编辑器 HX为md强化了众多功能,请务必点击【菜单-帮助-markdown语法示例】,快速掌握md及HX的强化技巧!

    6. 清爽护眼 HX的界面比其他工具更清爽简洁,绿柔主题经过科学的脑疲劳测试,是最适合人眼长期观看的主题界面 详见

    7. 强大的语法提示 HX是中国唯一一家拥有自主IDE语法分析引擎的公司,对前端语言提供准确的代码提示和转到定义(Alt+鼠标左键)

    8. 高效极客工具 更强大的多光标、智能双击...让字处理的效率大幅提升 了解HX的极客技巧,详见

    9. 更强的json支持 现代js开发中大量json结构的写法,HX提供了比其他工具更高效的操作 详见

    10. 丰富的快捷键

      如果你习惯了其他工具(如vscode或sublime)的快捷键,在菜单工具-快捷键方案中可以切换。

  2. 下载 HBuilderX 开发工具

    最新版本下载:https://www.dcloud.io/hbuilderx.html

    HBuilderX历史版本下载地址: https://ask.dcloud.net.cn/article/37302

    我们从历史版本中下载 2.9.3 ,如下图: ( ==不要用2.9.7+以上,新版本对 vedio 自定义视频播放竖/横屏有问题==)

    image-20201204093630818
  3. 下载好后,直接傻瓜式安装,安装后查看HuilderX版本,使用2.9.3.20201014版本

    image-20201204093138777
  4. 安装后,如果会弹出安装一个语法提示库插件,点击它进行安装(不弹就忽略它)。安装成功后,重启HuilderX

    image-20201204190121029

    image-20201204145156939

安装scss/sass编译

使用了scss/sass语法后需要编译为css。uni-app会自动编译或对文件右键-外部命令编译时使用。

  1. 浏览器访问下面链接,点击右侧 使用HBuilderX 入插件 > 弹出窗口点击 打开HBuilderX

    https://ext.dcloud.net.cn/plugin?name=compile-node-sass

    image-20201204144246805
  2. 在 HuilderX 会弹出是否安装,点击

    image-20201204144425473
  3. 安装成功后,在页面的style标签上使用 lang="scss" 后即可编写scss代码

      <style lang="scss">
      </style>

创建项目

  1. 文件-新建-项目
image-20201204092758982
  1. 打开新建项目窗口后,项目名 mxg-education-app , 具体如下操作,

image-20201204092920821

HBuilder 连接真机

HBuilder/HBuilderX真机运行、手机运行、真机联调常见问题 http://ask.dcloud.net.cn/article/97

Mac 连接iphone真机

新安装HBuilderX工具的要保证有App真机运行插件,有手机才会被HBuilder识别。

image-20201204190402043

上面是预告,连接步骤:

  1. 确认手机已通过数据线连接电脑

  2. 电脑下载iTunes,确认iTunes能正常连接手机

    (爱思官方可下:http://url.i4.cn/UjuIbiaa)

    image-20201204145505725
  3. 如手机屏幕弹出需信任本计算机的询问,请同意该授权

  4. 连接成功,在Hbuilder菜单栏上点击 运行 ,如下图就可以查看到手机型号,运行项目到手机上

    image-20201204145906431

    如果显示未检测到设备,就是Hbuilder没有识别到,连接失败,参见官方说明 http://ask.dcloud.net.cn/article/97

  5. 运行后,查看控制台到如下日志,说明APP已经安装到手机,

    image-20201204150501468
  6. 打开手机,查看桌面上已经有一个 HBuilder 的APP后,当前点击app还打不开,

  7. 然后如下操作后就可以打开APP了,步骤:

    "设置"---》"通用"---》"设备管理" (或"描述文件"。这步app安装成功后才找得到)--- 》找到 Digital Heaven 开头的证书 》 信任

    IMG_3085

Mac连接Android手机

  1. 关于本机(指==Mac系统的关于本机==,非手机) --> 系统报告 -> usb -> 你所连接的device --> 厂商ID或者供应商ID(Vendor ID)

    image-20201215170151450image-20201215170218066

    image-20201215170317054
  2. 在终端执行如下命令: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
  3. 重启HBuilderX。

  4. 如重启HBuilderX仍然不行,请使用命令行(终端.app),切换到HBuilderX自带的adb目录。

  5. HBuilderX正式版的adb目录位置:tools/adbs目录(MAC下为HBuilderX.app/Contents/tools/adbs目录)

  6. HBuilderX Alpha版的adb目录位置:plugins/launcher/tools/adbs目录(MAC下为/Applications/HBuilderX-Alpha.app/Contents/HBuilderX/plugins/launcher/tools/adbs目录)

  7. 在adbs目录下运行./adb kill-server重试。

  8. 重启电脑重试。

Windows连接Android手机

确认已安装Android手机驱动

如果手机连接没有任何反应或提示驱动问题,可通过以下方式解决:

  1. 装驱动比较好的方式是使用各种手机助手,比如360、腾讯的各种手机助手,如果有问题,尝试升级助手的版本。
  2. 打开手机开发者模式,(不同机型打开方式不一样,自行百度)一般是找到机器版本号。如打开开发者模式:关于手机》设备停止》版本号 (多点击它几下,会提示已打开开发者模式)
  3. 找下手机是否有个 usb调试,打开它

Windows 连接iphone真机

  1. 确认手机已通过数据线连接电脑

  2. 确认已安装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 版本会出现以下情况,所以不使用这个版本:

    iphone连接

    • 12.11.0.26版本itunes连接上,但是HBuilder识别不到;或者itunes连接不上手机

      ==如果出现上面情况,安装 04-配套软件\itoolssetup_4500.exe 工具,然后手机usb连接电脑,打开 itools 工具,它会自动修复驱动,需要等待10分钟左右。等itools识别到了后,将 HBuilderX重启,就可以识别到了。==

      1608105877217

    • 如果重新安装itunes 识别不到iphone,没有卸载干净,按下面网站卸载

      https://zhidao.baidu.com/question/1731993899251396907.html

      apple官网提示(我测试无效):https://discussionschinese.apple.com/thread/79226

  3. 确认iTunes能正常连接手机

  4. 如手机屏幕弹出需信任本计算机的询问,请同意该授权

    如果不小心点了不信任,可请前往“设置”>“通用”>“还原”>“还原位置与隐私”

  5. 如果是第一次安装完itunes,建议重新启动HBuilderX

  6. 如果以上方案都无法解决,有可能是因为本地库与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或者重试真机运行

  7. 有可能是iTunes安装时依赖库丢失,尝试重装iTunes解决问题

  8. iTools提供了一个修复驱动的工具和教程,可以参考http://bbs.itools.cn/thread-129390-1-1.html

运行到微信小程序

  1. 下载微信小程序开发工具稳定版: https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

  2. 安装微信小程序开发者工具

  3. 运行到微信小程序,如下

    image-20201204181946995
  4. 如果是第一次使用,需要先配置小程序ide的相关路径,才能运行成功。如下图,需在输入框输入微信开发者工具的安装路径。 若HBuilderX不能正常启动微信开发者工具,需要开发者手动启动,然后将uni-app生成小程序工程的路径拷贝到微信开发者工具里面,在HBuilderX里面开发,在微信开发者工具里面就可看到实时的效果。

    img

微信小程序真机预览

  1. 访问 https://mp.weixin.qq.com/ 注册微信小程序个人帐号,注册后,再登录如下操作查看AppID

    image-20201204181341702
  2. 打开HBuilderX工具中,项目的 mainfest.json 文件,点击微信小程序 将AppID粘贴进入就可以了,

    image-20201204181135285
  3. 打开工具,点击右上角 详情 》基本信息》会有一个AppID框,将上面复制的AppID粘贴即可。

    image-20201204181635025

    1608114901757

  4. 点击菜单栏的 预览》自动预览》编译并预览,你打开小程序绑定的微信号,它就会自动运行打开小程序

    1608115070598

报错: Cannot read property 'forceUpdate' of undefined

1610767106541

解决:

image-20201204181135285

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 官方文档内容说明,根据官方导航栏模块查找知识:

image-20210116155837293

  • 搜索框:有疑问直接搜索框输入,BUG直接复制错误提示粘贴上去搜索。

  • 介绍:先看这个页面,就知道uniapp大体知识,覆盖了哪些内容,如何进行开发。

  • 框架:pages.json 配置项、生命周期、页面通讯、日志打印、定时器。

  • API: 为开发APP、小程序、H5等提供的内置函数。

  • uniCloud: 简化服务端开发,不用自己开发服务端代码。

项目目录及文件介绍

  1. 一个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 的代码,不经过转换直接运行,在手机设备上会报错。
  • cssless/scss 等资源同样不要放在 static 目录下,建议这些公用的资源放在 common 目录下。

总结

  • ==static 目录放图片、视频资源。common目录放 jscssless/scss 等资源,components 目录放可复用vue组件==

资源路径说明

vue组件中引入静态资源

说明

  • template内引入静态资源,如imagevideo等标签的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 字体图标

下载图标库

  1. 进入阿里巴巴矢量图标库https://www.iconfont.cn/,添加图标到项目,然后下载至本地

    image-20201204161751732

  2. 下载解压后的本地文件如下:

image-20201204161836412

  1. 把 iconfont.css 和 iconfont.ttf 文件拷贝到 /static/icon/ 目录下

image-20201207095206295

  1. 修改 iconfont.css (Hbuilder 工具取消自动换行(视图》自动换行),不管多长都在一行显示)

    修改后如下图,注意 src 最后加上个分号

    image-20201204162924206 image-20201204163102717

vue 文件引用字体图标

方式一:Unicode 引用步骤

Unicode 是字体在网页端最原始的应用方式,特点是:

  • 兼容性最好,支持 IE6+,及所有现代浏览器。
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • 但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。
  • 多色有需求建议使用 symbol 的引用方式
  1. 在 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://==):

    image-20201204124510509
  2. 挑选相应图标并获取字体编码,应用于页面

    注意:类名是 iconfont ,字体编码&#开头 ;结尾

    <text class="iconfont">&#xe64e;</text>

方式二:Font-class 类名引用步骤(推荐方式)

font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。

与 Unicode 使用方式相比,具有如下特点:

  • 兼容性良好,支持 IE8+,及所有现代浏览器。
  • 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
  • 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
  • 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
  1. 在 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://==)微信小程序不支持网络链接,只支持本地方式:

    image-20201204123927512
  2. 挑选相应图标并获取类名,应用于 .vue 页面

    注意:iconfonticon-haopingiconfont.css 文件声明的,icon-haoping 是具体的图标类名

    <text class="iconfont icon-haoping"></text>

    当前使用 font-class 方式引入字体图标后,也可以采用Unicode字符编码方式使用图标。

    <text class="iconfont">&#xe64e;</text>

nvue 文件引用字体图标

说明

  • nvue 要使用 Unicode 引用。

  • nvue 文件中不可直接使用css的方式引入字体文件,需要在每个nvue文件中使用js的方式引入。无法App.vue全局引入。

  • nvue不支持本地路径引入字体,请==使用网络链接或者base64形式。==

步骤

  1. 比如在 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>
  2. style 中声明 .iconfont 引用上面加载的字体文件,定义图标大小和颜色。

    注意:==下面 font-family 的值对应上面 js 中的 fontFamily 值。==

    <style>
    /* 
    针对 nvue 文件中使用字体图标,导入Unicode文件 iconfont.ttf,
    使用 <text class="iconfont">&#xe65a;</text>
     */
    .iconfont {
        font-family: iconfont; /* iconfont 对应上面 fontFamily 的值, */
        font-size: 50rpx;
        color: #FFFFFF;
    }
    </style>
  3. 挑选相应图标并获取字体编码,应用于 .nvue 页面

    注意:类名是 iconfont ,字体编码&#开头 ;结尾

    <text class="iconfont">&#xe65a;</text>

彩色图标 iconfont

  1. 进入阿里巴巴矢量图标库https://www.iconfont.cn/,添加图标到项目,然后下载至本地

    image-20201204153042546

    解压后的本地文件如下,核心的是 iconfont.eot 文件。

    image-20201204153127930
  2. 打开电脑命令行,执行以下命令,全局安装 iconfont-tools 转换工具

    npm install -g iconfont-tools
  3. 执行cd命令进入第1步解压后的文件夹后,再执行如命令,然后回车

    iconfont-tools

    回车后,根据提示输入对应的值,与下图保持一致,后面需要使用:

    image-20201204155745647

  4. 执行完后,就会多出来一个iconfont-app 的文件夹

    image-20201204153759164
  5. 进入iconfont-app 文件夹,将其中的 iconfont-app-icon.css 复制到项目的 /static/icon/ 目录下

    image-20201204153846124

  6. 然后在 App.vue 引入该文件

    <style>
    /* 彩色的图标*/
    @import url("~@/static/icon/iconfont-weapp-icon.css");
    </style>
  7. 使用:其中 mxg-icon 开头是必须的

    <text class="mxg-icon mxg-icon-list-color"></text>
  8. 彩色图标当前对 vue文件有效,控制台会关于 backgroud 的相关警告,可忽略它

==大总结==

关于字体图标大总结:

  1. 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>
  2. nvue 文件使用Unicode字符编码方式,在每个要使用图标的 .nvue 文件中分别引入iconfont.ttf图标文件,

    • 引入方式具体参见上面 nvue 文件引用字体图标

    • 模板中使用:

      <text class="iconfont">&#xe64e;</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; 报错监听 )
onPageNotFound 页面不存在监听函数==(目前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 挂载到实例上去之后调用。详见 注意:此处并不能确定子组件被全部挂载,如果需要子组件完全挂载之后在执行操作可以使用$nextTickVue官方文档
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 ;

组件(模板)的条件编译

<!--  #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 时才会编译进去。

img

不同平台下的特有功能,以及小程序平台的分包,都可以通过 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 * 元素在设计稿中的宽度 / 设计稿基准宽度

举例说明:

  1. 若设计稿宽度为 750px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在 uni-app 里面的宽度应该设为:750 * 100 / 750,结果为:100rpx。
  2. 若设计稿宽度为 640px,元素 A 在设计稿上的宽度为 100px,那么元素 A 在 uni-app 里面的宽度应该设为:750 * 100 / 640,结果为:117rpx。
  3. 若设计稿宽度为 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开发肯定是有区别的。

  1. nvue 页面控制显隐只可以使用v-if不可以使用v-show
  2. nvue 页面只能使用flex布局,不支持其他布局方式。页面开发前,首先想清楚这个页面的纵向内容有什么,哪些是要滚动的,然后每个纵向内容的横轴排布有什么,按 flex 布局设计好界面。
  3. nvue 页面的布局排列方向默认为竖排(column),如需改变布局方向,可以在 manifest.json -> app-plus -> nvue -> flex-direction 节点下修改,仅在 uni-app 模式下生效。详情
  4. nvue页面编译为H5、小程序时,会做一件css默认值对齐的工作。因为weex渲染引擎只支持flex,并且默认flex方向是垂直。而H5和小程序端,使用web渲染,默认不是flex,并且设置display:flex后,它的flex方向默认是水平而不是垂直的。所以nvue编译为H5、小程序时,会自动把页面默认布局设为flex、方向为垂直。当然开发者手动设置后会覆盖默认设置。
  5. 文字内容,必须、只能在<text>组件下。不能在<div><view>text区域里直接写文字。否则即使渲染了,也无法绑定js里的变量。
  6. 只有text标签可以设置字体大小,字体颜色。
  7. 布局不能使用百分比、没有媒体查询。
  8. nvue 切换横竖屏时可能导致样式出现问题,建议有 nvue 的页面锁定手机方向。
  9. 支持的css有限,不过并不影响布局出你需要的界面,flex还是非常强大的。详见
  10. 不支持背景图。但可以使用image组件和层级来实现类似web中的背景效果。因为原生开发本身也没有web这种背景图概念
  11. css选择器支持的比较少,只能使用 class 选择器。详见
  12. nvue 的各组件在安卓端默认是透明的,如果不设置background-color,可能会导致出现重影的问题。
  13. class 进行绑定时只支持数组语法。
  14. Android端在一个页面内使用大量圆角边框会造成性能问题,尤其是多个角的样式还不一样的话更耗费性能。应避免这类使用。
  15. nvue页面没有bounce回弹效果,只有几个列表组件有bounce效果,包括 listrecycle-listwaterfall
  16. 原生开发没有页面滚动的概念,页面内容高过屏幕高度并不会自动滚动,只有部分组件可滚动(listwaterfallscroll-view/scroller),要滚得内容需要套在可滚动组件下。这不符合前端开发的习惯,所以在 nvue 编译为 uni-app模式时,给页面外层自动套了一个 scroller,页面内容过高会自动滚动。(组件不会套,页面有recycle-list时也不会套)。后续会提供配置,可以设置不自动套。
  17. 在 App.vue 中定义的全局js变量不会在 nvue 页面生效。globalDatavuex是生效的。
  18. App.vue 中定义的全局css,对nvue和vue页面同时生效。如果全局css中有些css在nvue下不支持,编译时控制台会报警,建议把这些不支持的css包裹在条件编译里,APP-PLUS-NVUE
  19. 不能在 style 中引入字体文件,nvue 中字体图标的使用参考:加载自定义字体。如果是本地字体,可以用plus.io的API转换路径。
  20. 目前不支持在 nvue 页面使用 typescript/ts
  21. 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-areamovable-view

movable-areamovable-view组件组合使用,实现可拖动区域组件。由于app和小程序的架构是逻辑层与视图层分离。

movable-area指代可拖动的范围,在其中内嵌movable-view组件用于指示可拖动的区域。其中movable-view必须在movable-area组件中,并且必须是直接子节点,否则不能移动。

即手指/鼠标按住movable-view拖动或双指缩放,但拖不出movable-area规定的范围。

当然也可以不拖动,而使用代码来触发movable-viewmovable-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。
  • 百度、字节跳动小程序文档未说明大小限制

除此之外,其他数据存储方案:

  • H5端还支持websql、indexedDB、sessionStorage
  • App端还支持SQLiteIO文件等本地存储方案。

相关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();

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

发送后台服务器请求接口数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问