跨平台开发uni-app
uni-app的开发规范
页面遵循vue单文件组件(SFC)规范
接口能力靠近微信小程序规范 但需将前缀wx替换为uni
数据绑定及事件处理同Vue.js规范 同时补充了App及页面的生命周期
为了兼容多端运行 建议使用flex布局 推荐使用rpx单位(750设计稿)
main.js
main.js是uni-app的入口文件 主要作用是
初始化vue实例
定义全局属性
定义全局组件
安装插件 如pinia,vuex等
vue2中
import Vue from 'vue'
Vue.config.productionTip = false //vue3 不在需要
App.mpType = 'app' //vue3不在需要
const app = new Vue({
...App
})
app.$mount()
vue3中
import { createSSRApp } from 'vue'
//不能修改导出的createApp方法名 不能修改从Vue中导入的createSSRApp
export function createApp() {
const app = createSSRApp(App)
return {
app
}
}
引入Pinia
import { createSSRApp } from 'vue'
import * as Pinia from 'pinia'
//不能修改导出的createApp方法名 不能修改从Vue中导入的createSSRApp
export function createApp() {
const app = createSSRApp(App)
return {
app
Pinia, //此处必须将Pinia返回
}
}
App.vue
App.vue入口文件
App.vue是uni-app的入口组件 所有页面都是在App.vue下进行切换
App.vue本身不是页面 这里不能编写视图元素 也就是没有< template >元素
App.vue的作用
- 应用的生命周期
- 编写全局样式
- 定义全局数据globalData
注意:应用生命的周期仅可以在App.vue中监听 在页面监听无效
<script>
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<!-- 不支持添加scope 添加样式无效 -->
<style>
/*每个页面公共css 属于全局样式了 这里的样式没有作用域 */
</style>
全局与局部样式
全局样式
App.vue中style的样式为全局样式 作用于每一个页面(style标签不支持scoped 写了导致样式无效)
App.vue中通过@import 语句可以导入外联样式 一样作用于每一个界面
uni.scss文件也是用来编写全局公共样式 通常用来定义全局变量
uni.scss中通过@import 语句可以导入外联样式 一样作用于每一个界面
局部样式
在pages目录下的vue文件的style中的样式为局部样式 只作用对应的页面 并会覆盖App.vue中相同的选择器
vue文件中的style标签也可支持scss等预处理器 比如 安装dart-scss插件后 style标签便可支持Scss写样式了
style标签支持scoped吗 不支持 不需写
uni.scss
uni.scss全局样式文件
为了方便整体控制应用风格 默认定义了uni-app框架内置全局变量 当然也可以存放自定义的全局变量等
在uni.scss中定义的变量 我们无需@import就可以在任意组件中直接调用
使用uni.scss中的变量 须在 HBuilderX里面安装Scss插件(scss/sass编译)
然后在该组件的Style上加lang = “scss” 重启即可生效
uni.scss 文件
$my-primary-color: red;
<style lang='scss'>
/* 局部样式 类似给Style添加了scoped */
.content{
color: $my-primary-color
}
</style>
注意:
这里的uni-app框架内置变量和后i按uni-ui组件库的内置变量是不一样的
uni.scss定义的变量是全局可以直接使用 App.vue定义的变量只能在当前组件使用
页面调用接口
- getApp() 函数(兼容h5, weapp, app)
- 用于获取当前应用实例 可用于获取globalData
- getCurrentPages() 函数 (兼容h5, weapp, app)
- 用于获取当前页面栈的实例 以数组形式按栈的顺序给出
- 数组: 第一个元素为首页 最后一个元素为当店页面
- 仅用于展示页面栈的情况 请勿修改页面栈 以免造成页面状态错误
- 常用方法如下图所示
- 用于获取当前页面栈的实例 以数组形式按栈的顺序给出
方法 | 描述 | 平台说明 |
---|---|---|
page.$getAppWebview() | 获取当前页面的webview对象实例 | App |
page.route | 获取当前页面的路由 |
App.vue
<script>
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
},
globalData:{
text: 'text'
}
}
</script>
<style>
/*每个页面公共css */
</style>
<template>
<view class="content">
<view class="title name box">1.全局变量</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'Hello'
}
},
// 页面的生命周期
onLoad() {
// console.log(this); // Vue的实例
// 1.拿到全局数据 globalData
const app = getApp() // weapp h5 app
console.log("globalData=", app.globalData);
// 2.拿到当前页面的路由
const pages = getCurrentPages()
console.log(pages[pages.length - 1].route);
},
// 属于的Vue组件的生命周期
beforeCreate() {},
created() {
},
methods: {
}
}
</script>
<style lang="scss">
// @import '@/static/css/base.scss';
// 默认就是局部样式
.box{
border-radius: $radius;
}
page{
// height: auto;
}
</style>
page.json
page.json全局页面配置(兼容h5, weapp, app)
page.json文件用来对uni-app进行全局配置 类似微信小程序中app.json
决定页面的路径 窗口样式 原生的导航栏 底部的原生tabbar等
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
}
}
manifest.json
manifest.json应用配置
- Android平台相关配置
- iOS平台相关配置
- Web端相关的配置
- 微信小程序相关配置
- …
常用内置组件
view: 视图容器 类似于传统html中的div 用于包裹各种元素内容(视图容器可以使用div吗?可以 但div不跨平台)
text: 文本组件 用于包裹文本内容
button: 在小程序端的主题和在其他端的主题颜色不一样 (可以通过条件编译来统一风格)
image: 图片 默认宽度 320px 高度240px
- 仅支持相对路径 绝对路径 支持导入 支持base64编码
scrollview: 可滚动视图区域 用于区域滚动
- 使用竖向滚动时 需要给< scroll-view > 一个固定高度 通过css设置height
- 使用横向滚动时 需要给< scroll-view > 添加一个white-space: nowrap样式 子元素设置为行内块级元素
- App和小程序中 请勿在scroll-view中使用map vieo等原生组件
- 小程序的scroll-view中也不要使用canvas textarea原生组件
- 若要使用下拉刷新 建议使用页面的滚动 而不是scroll-view
swiper: 滑块视图容器 一般用于左右滑动或上下滑动 比如banner轮播图
- 默认宽 100%, 高150px 可设置swiper组件高度来修改默认高度 图片高可用100%
尺寸单位rpx
uni-app支持的通用css单位包括 px rpx(推荐单位) vh vw
- px即 屏幕像素 rpx是响应式像素(responsive pixel)可以根据屏幕宽度进行自适应
- 规定屏幕宽度为750rpx 如在iPhone6上 屏幕宽度为375px 共有750个物理像素 则750rpx = 375px = 750物理像素 1rpx = 0.5px = 1物理像素
- 建议: 开发微信小程序时设计师可以用iPhone6作为设计稿的标准(即:设计稿宽度为750px)
页面的宽度在uni-app中的宽度计算公式:
750 * 元素在设计稿中的宽度 / 设计稿基准宽度
若设计稿宽度为750px 元素A在设计稿上的宽度为100px 那么元素A在uni-app里的宽度应该设置 750100 / 750
若设计稿宽度为640px 元素A在设计稿上的宽度为100px 那么元素A在uni-app里的宽度应该设置 750100 / 640
若设计稿宽度为475px 元素A在设计稿上的宽度为200px 那么元素A在uni-app里的宽度应该设置 750*200 / 475
样式导入
使用@import语句可以导入外联样式(scss或css)
@import后跟需要导入的外联样式表的相对路径 用;表示语句结束
除了相对路径 默认是支持绝对路径(即@别名前缀)
相对路径: …/…/common/base.css
绝对路径: @/static/common/base.css
背景图片
uni-app支持使用在css里设置背景图片 使用方式与普通web项目大体相同 但需要注意以下几点
- 支持base64格式图片 支持网络路径图片
- 小程序不支持在css中使用本地文件 包括背景图和字体文件 需转成base64后使用
- 使用本地背景图片或字体图标需注意
- 为方便开发者 在背景图片小于40kb时 uni-app编译到不支持本地背景图的平台时 会自动将其转化为base64格式
- 图片大于等于40kb 会有性能问题 不建议使用太大的背景图 如开发者必须使用 则需自己将其转换为base64格式使用 或将其挪到服务器上 从网络地址引用
- bending背景图片的应用路径推荐使用**~@**开头的绝对路径
注意:
微信小程序不支持相对路径 (真机不支持 开发工具支持)
字体图标
uni-app支持使用字体图标 使用方式与普通web项目相同 注意事项也和背景图片一样 使用步骤如下
先制作字体图标, 比图: 可以在iconfont网站中生成
将字体图标文件引入项目,比如iconfont.ttf
在全局的Css中引入字体图标 比如App.vue
@font-face {
font-family: "iconfont"; /* Project id */
src: url('~@/static/custom-font/iconfont.ttf') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-shouye:before {
content: "\e668";
}
扩展组件(uni-ui)
什么是 uni-ui
- uni-ui是DCloud提供的一个UI组件库 一套基于Vue组件 flex布局的跨全端UI框架
- uni-ui不包括uni-app框架提供的基础组件 而是基础组件的补充
uni-app的特点
高性能
- 目前 在小程序与混合App领域 uni-ui是性能的标杆
- 自动差量更新 uni-app引擎底层会自动用diff算法更新数据
- 优化逻辑层和视图层通讯折损 比如 需要跟手式操作的UI组件 底层使用了wxs bindingx等拘束 实现了高性能的交互体验
- WXS(WeiXin Script)是小程序的一套脚本语言 结合WXML 可以构建出页面的结构
- bindingx技术提供了一种称之为表达式绑定的机制 在weex上让手势等复杂交互操作以60fps的帧率 流畅执行
全端
- uni-ui 的组件都是多端自适应的 底层会抹平很多小程序平台的差异或bug
- uni-ui还支持nvue原生渲染 以及PC宽屏设备
- 支持uni.scss 可以方便的扩展和切换应用的风格
安装uni-ui组件库
方式一(推荐):通过 uni_modules(插件模块化规范)单独安装组件,通过 uni_modules 按需安装某个组件:
- 步骤1:官网找到扩展组件清单,然后将所需要的组件导入到项目,导入后直接使用,无需import和注册。
- 步骤2:通常我们还想切换应用风格,这时可以在uni.scss导入uni-ui提供的内置scss变量,然后重启应用。
- 注意:需要登录 DCloud 账号才能安装
方式二(推荐) :通过 uni_modules 导入全部组件 - 如想把所有uni-ui组件导入到项目,可以借用Hbuilder X插件导入。
- 如没自动导入其他组件,可在 uni-ui 组件目录上右键选择 安装三方插件依赖 即可。
方式三:在 HBuilderX 新建 uni-app项目时,在模板中选择 uni-ui 模板来创建项目 - 由于uni-app独特的easycom(自动导包)技术,可以免引入、注册,就直接使用符合规则的vue组件。
方式四:npm安装 - 在 vue-cli 项目中可用 npm 安装 uni-ui 库
- 或直接在 HBuilderX 项目中用 npm安装 。
定制uni-ui主题风格
在项目根目录的uni-scss文件中引入uni-ui组件库的variable.scss变量文件 然后就可以使用或修改对应的scss变量
变量主要定义的是主题色
/* 需要放到文件最上面 */
@import '@/uni_modules/uni-scss/variables.scss'
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color:#333;//基本色
$uni-text-color-inverse:#fff;//反色
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable:#c0c0c0;
uni-froms组件
uni-froms组件使用步骤(类似Elment Plus的表单组件用法)
- 安装uni-froms等组件
- uni-froms搭建表单布局
- 编写表单项的验证规则
- 提交表单时验证表单项
- 重置表单
重写uni-froms组件样式
小程序 App直接重写 需要添加important
H5 App和小程序使用: global(selector) 需要添加important
H5 App和小程序使用:deep(selector) 需要添加important
//重写样式 (这个是微信小程序 直接重写就行)
.uni-forms-item__label {
justify-content: center !important;
color: red !import
}
//重写样式 (h5支持 和 小程序 支持)
:global(.uni-forms-item__label) {
color: purple !important;
justify-content: center !important;
}
//重写样式: deep 深度样式 h5支持
:deep(uni-forms-item__label) {
justify-content: center !important;
color: green !important;
}
跨平台兼容
uni-app能实现一套代码 多端运行 核心是通过编译器 + 运行时实现的
- 编译器:将uni-app统一代码编译生成每个平台支持的特有代码;如在小程序平台,编译器将**.vue文件拆分生成wxml、wxss、js**等。
- 运行时:动态处理数据绑定、事件代理,保证 Vue和对应宿主平台 数据的一致性;
跨平台存在的问题: - uni-app 已将常用的组件、JS API 封装到框架中,开发者按照 uni-app 规范开发即可保证多平台兼容,大部分业务均可直接满足。
- 但每个平台有自己的一些特性,因此会存在一些无法跨平台的情况。
- 大量写 if else,会造成代码执行性能低下和管理混乱。
- 编译到不同的工程后二次修改,会让后续升级变的很麻烦。
跨平台兼容解决方案:
- 在 C 语言中,通过 #ifdef、#ifndef 的方式,为 windows、mac 等不同 os 编译不同的代码。
- uni-app 参考这个思路,为 uni-app 提供了条件编译手段,在一个工程里优雅的完成了平台个性化实现。
条件编译
条件编译是用特殊的注释作为标记 在编译时根据这些特殊的注释 将注释里面的代码编译到不同平台
具体的语法:以 #ifdef 或 #ifndef 加 %PLATFORM% 开头,以 #endif 结尾。
- #ifdef:if defined 仅在某平台存在
- #ifndef:if not defined 除了某平台均存在
- %PLATFORM%:平台名称
支持条件编译的文件 - .vue(template 、script 、style)
- .js 、.css 、pages.json
- 各预编译语言文件,如:.scss、.less、.stylus、.ts、.pug
例如:设置页面的标题 - H5专有API:document.title = ’’
- 微信小程序专有API:wx.setNavigationBarTitle(object)
条件编译-注意事项
条件编译是利用注释实现的 在不同语法里注释写法不一样
js使用//注释
css使用/* 注释 */
vue/nvue 模板里使用 < !-- 注释 -->
条件编译 APP-PLUS 包含 :APP-NVUE 和 APP-VUE
- APP-PLUS-NVUE 和 APP-NVUE 没什么区别,为了简写后面出了 APP-NVUE
- 使用条件编译请保证编译前和编译后文件的正确性,比如 json 文件中不能有多余的逗号
- Android 和 iOS 平台不支持条件编译,如需区分 Android、iOS 平台,请通过调用 uni.getSystemInfo 来获取平台信息
- 微信小程序主题色是绿色,而百度支付宝小程序是蓝色,应用想分平台适配颜色,条件编译是代码量最低、最容易维护的
新建page页面
uni-app页面是编写在pages目录下
- 可直接在uni-app项目右上角“新建页面” HBuilderX会自动在pages.json中完成页面注册
注意事项: - 每次新建页面,需在pages.json中配置pages列表(手动才需配置)
- 未在pages.json -> pages 中配置的页面,uni-app会在编译阶段进行忽略。
删除页面: - 删除.vue文件 和 pages.json中对应的配置
页面路由
uni-app 有两种页面路由跳转方式:使用navigator组件跳转、调用API跳转(类似小程序,与vue-router不同)。
- 组件:navigator
- API:navigateTo、redirectTo、navigateBack、switchTab
页面间通讯
在uni-app中,常见页面通讯方式:
方式一:url查询字符串和EventChannel
方式二:使用事件总线
方式三:全局数据 globalData
方式四:本地数据存储
方式五:Vuex和Pinia,状态管理库。
方式一:url和EventChannel(兼容h5、weapp、app)
直接在url后面通过查询字符串的方式拼接
如url查询字符串出现特殊字符等格式,需编码
然后可在onLoad生命周期中获取url传递的参数
EventChannel 对象的获取方式
Options语法:this.getOpenerEventChannel()
Composition语法:getCurrentInstance().proxy. getOpenerEventChannel()
事件总线
方式二 事件总线
uni.$ emit(eventName, OBJECT) 触发全局的自定义事件
uni.$ on(eventName, callback) 监听全局的自定义事件 有uni.$ emit触发
uni.$ once(eventName, callback) 只监听一次全局的自定义事件 由uni.$ emit触发
uni.$ off(eventName, callback) 移除全局自定义事件监听器
如果没有提供参数 则移除所有的事件监听器
注意事项
需先监听 再触发事件 比如 你在A界面触发 然后跳转到B页面后才监听是不行的
通常on 和 off 是同时使用 可以避免多次重复监听
适合页面返回传递参数 适合跨组件通讯 不适合界面跳转传递参数
页面生命周期(Options API)
uni-app 常用的页面生命周期函数:
- onLoad(options) -> onload
- onShow -> onShow
- onReady -> onReady
- onHide -> onHide
- onUnload -> onUnload
- onPullDownRefresh -> onPullDownRefresh
- onReachBottom -> onReachBottom
- …
页面可以使用Vue组件生命周期吗? 可以
页面生命周期(Composition API)
uni-app 常用的页面生命周期函数:
- onLoad -> onload
- onShow -> onShow
- onReady -> onReady
- onHide -> onHide
- onUnload -> onUnload
- onPullDownRefresh -> onPullDownRefresh
- onReachBottom -> onReachBottom
网络请求
uni.request(OBJECT) 发起网络请求。
- 登录各个小程序管理后台,给网络相关的 API 配置合法域名(域名白名单)
- 微信小程序开发工具,在开发阶段可以配置:不校验合法域名
- 运行到手机时,资源没有出来时可以打开手机的调试模式
- 请求的 header 中 content-type 默认为 application/json
数据缓存
uni.setStorage(OBJECT)
- 将数据存储在本地缓存中指定的key中 会覆盖掉原来key对应的内容 这是一个异步接口
uni.setStorageSync(KEY, DATA) - 将data存储在本地缓存中指定的key中 会覆盖掉原来该key对应的内容 这是一个同步接口
uni.getStorage(OBJECT) - 从本地缓存中异步获取指定key对应的内容
uni.getStorageSync(KEY, DATA) - 从本地缓存中同步获取指定key对应的内容
uni.removeStorage(OBJECT) - 从本地缓存中异步移除指定key
uni.removeStorageSync(KEY) - 从本地缓存中同步移除指定key
组件(Component)
uni-app 组件Vue标准组件基本相同 但是也有一点区别 比如
- 传统vue组件 需要创建组件、引用、注册 三个步骤后才能使用组件 easycom组件模式可以将其精简为一步
easycom组件规范 - 组件需符合components/组件名称/组件名称.vue的目录结构
- 符合以上目录结构的就可不用引用、注册 直接在页面中使用该组件了
组件生命周期
uni-app 组件支持的生命周期,与Vue组件的生命周期相同。
- 组件中可以使用页面的生命周期吗?
- 在Options API语法 组件中不支持使用页面生命周期
- 在Composition API语法 组件中支持页面生命周期 不同端支持情况有差异