uni-app
是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。DCloud
公司拥有900万开发者、数百万应用、12亿手机端月活用户、数千款uni-app插件、70+微信/qq群。阿里小程序工具官方内置uni-app(详见),腾讯课堂官方为uni-app录制培训课程(详见),开发者可以放心选择。uni-app
在手,做啥都不愁。即使不跨端,uni-app
也是更好的小程序开发框架(详见)、更好的App跨平台框架、更方便的H5开发框架。不管领导安排什么样的项目,你都可以快速交付,不需要转换开发思维、不需要更改开发习惯。HBuilderX是通用的前端开发工具,但为uni-app
做了特别强化。
下载App开发版,可开箱即用;如下载标准版,在运行或发行uni-app
时,会提示安装uni-app
插件,插件下载完成后方可使用。
如使用cli
方式创建项目,可直接下载标准版,因为uni-app编译插件被安装到项目下了
选择uni-app
类型,输入工程名,选择模板,点击创建,即可成功创建。
uni-app自带的模板有 Hello uni-app ,是官方的组件和API示例。还有一个重要模板是 uni ui项目模板,日常开发推荐使用该模板,已内置大量常用组件。
如手机无法识别,请点击菜单运行-运行到手机或模拟器-真机运行常见故障排查指南。 注意目前开发App也需要安装微信开发者工具。
uni-app官网
uni-app官网
uni-app官网
uni-app官网
代码示例:
"condition": { //模式配置,仅开发期间生效
"current": 0, //当前激活的模式(list 的索引项)
"list": [{
"name": "swiper", //模式名称
"path": "pages/component/swiper/swiper", //启动页面,必选
"query": "interval=4000&autoplay=false" //启动参数,在页面的onLoad函数里面得到。
},
{
"name": "test",
"path": "pages/component/switch/switch"
}
]
}
vue页面支持下面这些普通H5单位,但在nvue里不支持:
@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束。代码示例:
定义在app.vue中
示例代码
pages.json
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app",
"enablePullDownRefresh": true
}
}
],
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarBackgroundColor": "#0faeff",
"backgroundColor": "#fbf9fe"
}
}
index.vue
// 仅做示例,实际开发中延时根据需求来使用。
export default {
data() {
return {
text: 'uni-app'
}
},
onLoad: function (options) {
setTimeout(function () {
console.log('start pulldown');
}, 1000);
uni.startPullDownRefresh();
},
onPullDownRefresh() {
console.log('refresh');
setTimeout(function () {
uni.stopPullDownRefresh();
}, 1000);
}
}
注意
startPullDownRefresh
在开发者工具里会提示暂未开放,请勿使用
startPullDownRefresh
请使用真机调试(非真机预览)示例代码
uni.request({
url: 'https://www.example.com/request', //仅为示例,并非真实接口地址。
data: {
text: 'uni.request'
},
header: {
'custom-header': 'hello' //自定义请求头信息
},
success: (res) => {
console.log(res.data);
this.text = 'request success';
}
});
将本地资源上传到开发者服务器,客户端发起一个 POST
请求,其中 content-type
为 multipart/form-data
。
如页面通过 uni.chooseImage 等接口获取到一个本地资源的临时文件路径后,可通过此接口将本地资源上传到指定服务器。另外选择和上传非图像、视频文件参考:uni-app 选择和上传非图像、视频文件 - DCloud问答。
在各个小程序平台运行时,网络相关的 API 在使用前需要配置域名白名单。
推荐开发者上传到uniCloud,uniCloud提供了免费CDN和更好的易用性,包括安全的cdn直传。
示例代码
uni.chooseImage({
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths;
uni.uploadFile({
url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址
filePath: tempFilePaths[0],
name: 'file',
formData: {
'user': 'test'
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data);
}
});
}
});
代码示例
uni.chooseImage({
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths;
const uploadTask = uni.uploadFile({
url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址
filePath: tempFilePaths[0],
name: 'file',
formData: {
'user': 'test'
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data);
}
});
uploadTask.onProgressUpdate((res) => {
console.log('上传进度' + res.progress);
console.log('已经上传的数据长度' + res.totalBytesSent);
console.log('预期需要上传的数据总长度' + res.totalBytesExpectedToSend);
// 测试条件,取消上传任务。
if (res.progress > 50) {
uploadTask.abort();
}
});
}
});
下载文件资源到本地,客户端直接发起一个 HTTP GET 请求,返回文件的本地临时路径。
在各个小程序平台运行时,网络相关的 API 在使用前需要配置域名白名单。在h5上是跨域的,用户需要处理好跨域问题。
OBJECT 参数说明
参数名 | 类型 | 必填 | 说明 | 平台差异说明 |
---|---|---|---|---|
url | String | 是 | 下载资源的 url | |
header | Object | 否 | HTTP 请求 Header, header 中不能设置 Referer。 | |
timeout | Number | 否 | 超时时间,单位 ms | H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+) |
success | Function | 否 | 下载成功后以 tempFilePath 的形式传给页面,res = {tempFilePath: '文件的临时路径'} | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) | |
filePath | string | 否 | 指定文件下载后存储的路径 (本地路径) | 微信小程序(IOS小程序保存到相册需要添加此字段才可以正常保存) |
注:文件的临时路径,在应用本次启动期间可以正常使用,如需持久保存,需在主动调用 uni.saveFile,才能在应用下次启动时访问得到。
success 返回参数说明
参数 | 类型 | 说明 |
---|---|---|
tempFilePath | String | 临时文件路径,下载后的文件会存储到一个临时文件 |
statusCode | Number | 开发者服务器返回的 HTTP 状态码 |
注意
超时时间
可以统一在 manifest.json
中配置 networkTimeout。示例
uni.downloadFile({
url: 'https://www.example.com/file/test', //仅为示例,并非真实的资源
success: (res) => {
if (res.statusCode === 200) {
console.log('下载成功');
}
}
});
返回值
如果希望返回一个 downloadTask
对象,需要至少传入 success / fail / complete 参数中的一个。例如:
var downloadTask = uni.downloadFile({
url: 'https://www.example.com/file/test', //仅为示例,并非真实接口地址。
complete: ()=> {}
});
downloadTask.abort();
如果没有传入 success / fail / complete 参数,则会返回封装后的 Promise 对象:Promise 封装
通过 downloadTask
,可监听下载进度变化事件,以及取消下载任务。
downloadTask 对象的方法列表
方法 | 参数 | 说明 | 最低版本 |
---|---|---|---|
abort | 中断下载任务 | * | |
onProgressUpdate | callback | 监听下载进度变化 | * |
onHeadersReceived | callback | 监听 HTTP Response Header 事件,会比请求完成事件更早,仅微信小程序平台 支持,规范详情 |
|
offProgressUpdate | callback | 取消监听下载进度变化事件,仅微信小程序平台 支持,规范详情 |
|
offHeadersReceived | callback | 取消监听 HTTP Response Header 事件,仅微信小程序平台 支持,规范详情 |
onProgressUpdate 返回参数说明
参数 | 类型 | 说明 |
---|---|---|
progress | Number | 下载进度百分比 |
totalBytesWritten | Number | 已经下载的数据长度,单位 Bytes |
totalBytesExpectedToWrite | Number | 预期需要下载的数据总长度,单位 Bytes |
示例
const downloadTask = uni.downloadFile({
url: 'http://www.example.com/file/test', //仅为示例,并非真实的资源
success: (res) => {
if (res.statusCode === 200) {
console.log('下载成功');
}
}
});
downloadTask.onProgressUpdate((res) => {
console.log('下载进度' + res.progress);
console.log('已经下载的数据长度' + res.totalBytesWritten);
console.log('预期需要下载的数据总长度' + res.totalBytesExpectedToWrite);
// 满足测试条件,取消下载任务。
if (res.progress > 50) {
downloadTask.abort();
}
});
示例代码
uni.setStorage({
key: 'storage_key',
data: 'hello',
success: function () {
console.log('success');
}
});
示例代码
try {
uni.setStorageSync('storage_key', 'hello');
} catch (e) {
// error
}
从本地缓存中异步获取指定 key 对应的内容。
代码示例
uni.getStorage({
key: 'storage_key',
success: function (res) {
console.log(res.data);
}
});
从本地缓存中同步获取指定 key 对应的内容。
示例代码
try {
const value = uni.getStorageSync('storage_key');
if (value) {
console.log(value);
}
} catch (e) {
// error
}
异步获取当前 storage 的相关信息。
示例代码
uni.getStorageInfo({
success: function (res) {
console.log(res.keys);
console.log(res.currentSize);
console.log(res.limitSize);
}
});
同步获取当前 storage 的相关信息。
示例代码
try {
const res = uni.getStorageInfoSync();
console.log(res.keys);
console.log(res.currentSize);
console.log(res.limitSize);
} catch (e) {
// error
}
从本地缓存中异步移除指定 key。
示例代码
uni.removeStorage({
key: 'storage_key',
success: function (res) {
console.log('success');
}
});
从本地缓存中同步移除指定 key。
示例代码
try {
uni.removeStorageSync('storage_key');
} catch (e) {
// error
}
同步清理本地数据缓存。
示例代码
try {
uni.clearStorageSync();
} catch (e) {
// error
}
uni-app的Storage在不同端的实现不同:
除此之外,其他数据存储方案:
从HBuilderX2.6.6+起,App-Android平台对本地storage数据存储进行了性能优化,它的具体优化方式和升级注意事项,详见:Android平台 storage性能优化说明 - DCloud问答
uni-app 已将常用的组件、JS API 封装到框架中,开发者按照 uni-app 规范开发即可保证多平台兼容,大部分业务均可直接满足。
但每个平台有自己的一些特性,因此会存在一些无法跨平台的情况。
在 C 语言中,通过 #ifdef、#ifndef 的方式,为 windows、mac 等不同 os 编译不同的代码。 uni-app
参考这个思路,为 uni-app
提供了条件编译手段,在一个工程里优雅的完成了平台个性化实现。
条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。
写法:以 #ifdef 或 #ifndef 加 %PLATFORM% 开头,以 #endif 结尾。
条件编译写法 | 说明 |
---|---|
#ifdef APP-PLUS |
仅出现在 App 平台下的代码 |
#ifndef H5 |
除了 H5 平台,其它平台均存在的代码 |
#ifdef H5 || MP-WEIXIN |
在 H5 平台或微信小程序平台存在的代码(这里只有||,不可能出现&&,因为没有交集 |
%PLATFORM% 可取值如下:
值 | 生效条件 |
---|---|
VUE3 | HBuilderX 3.2.0+ 详情 |
APP-PLUS | App |
APP-PLUS-NVUE或APP-NVUE | App nvue |
H5 | H5 |
MP-WEIXIN | 微信小程序 |
MP-ALIPAY | 支付宝小程序 |
MP-BAIDU | 百度小程序 |
MP-TOUTIAO | 字节跳动小程序 |
MP-LARK | 飞书小程序 |
MP-QQ | QQ小程序 |
MP-KUAISHOU | 快手小程序 |
MP-360 | 360小程序 |
MP | 微信小程序/支付宝小程序/百度小程序/字节跳动小程序/飞书小程序/QQ小程序/360小程序 |
QUICKAPP-WEBVIEW | 快应用通用(包含联盟、华为) |
QUICKAPP-WEBVIEW-UNION | 快应用联盟 |
QUICKAPP-WEBVIEW-HUAWEI | 快应用华为 |
支持的文件
注意:
// 注释
、css 使用 /* 注释 */
、vue/nvue 模板里使用
;编译前
和编译后
文件的正确性,比如json文件中不能有多余的逗号;VUE3
需要在项目的 manifest.json
文件根节点配置 "vueVersion" : "3"
uni.navigateTo(OBJECT)
保留当前页面,跳转到应用内的某个页面,使用uni.navigateBack
可以返回到原页面。
OBJECT参数说明
参数 | 类型 | 必填 | 默认值 | 说明 | 平台差异说明 |
---|---|---|---|---|---|
url | String | 是 | 需要跳转的应用内非 tabBar 的页面的路径 , 路径后可以带参数。参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔;如 'path?key=value&key2=value2',path为下一个页面的路径,下一个页面的onLoad函数可得到传递的参数 | ||
animationType | String | 否 | pop-in | 窗口显示的动画效果,详见:窗口动画 | App |
animationDuration | Number | 否 | 300 | 窗口动画持续时间,单位为 ms | App |
events | Object | 否 | 页面间通信接口,用于监听被打开页面发送到当前页面的数据。2.8.9+ 开始支持。 | ||
success | Function | 否 | 接口调用成功的回调函数 | ||
fail | Function | 否 | 接口调用失败的回调函数 | ||
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
object.success 回调函数
参数
Object res
属性 | 类型 | 说明 |
---|---|---|
eventChannel | EventChannel | 和被打开页面进行通信 |
示例
//在起始页面跳转到test.vue页面并传递参数
uni.navigateTo({
url: 'test?id=1&name=uniapp'
});
// 在test.vue页面接受参数
export default {
onLoad: function (option) { //option为object类型,会序列化上个页面传递的参数
console.log(option.id); //打印出上个页面传递的参数。
console.log(option.name); //打印出上个页面传递的参数。
}
}
// 2.8.9+ 支持
uni.navigateTo({
url: 'pages/test?id=1',
events: {
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
acceptDataFromOpenedPage: function(data) {
console.log(data)
},
someEvent: function(data) {
console.log(data)
}
...
},
success: function(res) {
// 通过eventChannel向被打开页面传送数据
res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' })
}
})
// uni.navigateTo 目标页面 pages/test.vue
onLoad: function(option) {
console.log(option.query)
// #ifdef APP-NVUE
const eventChannel = this.$scope.eventChannel; // 兼容APP-NVUE
// #endif
// #ifndef APP-NVUE
const eventChannel = this.getOpenerEventChannel();
// #endif
eventChannel.emit('acceptDataFromOpenedPage', {data: 'test'});
eventChannel.emit('someEvent', {data: 'test'});
// 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据
eventChannel.on('acceptDataFromOpenerPage', function(data) {
console.log(data)
})
}
url有长度限制,太长的字符串会传递失败,可改用窗体通信、全局变量,另外参数中出现空格等特殊字符时需要对参数进行编码,如下为使用encodeURIComponent
对参数进行编码的示例。
// 在test.vue页面接受参数
onLoad: function (option) {
const item = JSON.parse(decodeURIComponent(option.item));
}
注意:
this.getOpenerEventChannel()
方式获取eventChannel
,请换用this.$scope.eventChannel
来获取,具体方式请参考上述示例。uni.redirectTo(OBJECT)
关闭当前页面,跳转到应用内的某个页面。
OBJECT参数说明
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
url | String | 是 | 需要跳转的应用内非 tabBar 的页面的路径,路径后可以带参数。参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔;如 'path?key=value&key2=value2' |
success | Function | 否 | 接口调用成功的回调函数 |
fail | Function | 否 | 接口调用失败的回调函数 |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
示例
uni.redirectTo({
url: 'test?id=1'
});
注意:
uni.reLaunch(OBJECT)
关闭所有页面,打开到应用内的某个页面。
注意: 如果调用了 uni.preloadPage(OBJECT) 不会关闭,仅触发生命周期 onHide
OBJECT参数说明
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
url | String | 是 | 需要跳转的应用内页面路径 , 路径后可以带参数。参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔;如 'path?key=value&key2=value2',如果跳转的页面路径是 tabBar 页面则不能带参数 |
success | Function | 否 | 接口调用成功的回调函数 |
fail | Function | 否 | 接口调用失败的回调函数 |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
示例
uni.reLaunch({
url: 'test?id=1'
});
export default {
onLoad: function (option) {
console.log(option.id);
}
}
Tips:
uni.reLaunch
之后之前页面栈会销毁,但是无法清空浏览器之前的历史记录,此时navigateBack
不能返回,如果存在历史记录的话点击浏览器的返回按钮或者调用history.back()
仍然可以导航到浏览器的其他历史记录。uni.switchTab(OBJECT)
跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。
注意: 如果调用了 uni.preloadPage(OBJECT) 不会关闭,仅触发生命周期 onHide
OBJECT参数说明
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
url | String | 是 | 需要跳转的 tabBar 页面的路径(需在 pages.json 的 tabBar 字段定义的页面),路径后不能带参数 |
success | Function | 否 | 接口调用成功的回调函数 |
fail | Function | 否 | 接口调用失败的回调函数 |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
示例
pages.json
{
"tabBar": {
"list": [{
"pagePath": "pages/index/index",
"text": "首页"
},{
"pagePath": "pages/other/other",
"text": "其他"
}]
}
}
other.vue
uni.switchTab({
url: '/pages/index/index'
});
uni.navigateBack(OBJECT)
关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages()
获取当前的页面栈,决定需要返回几层。
OBJECT参数说明
参数 | 类型 | 必填 | 默认值 | 说明 | 平台差异说明 |
---|---|---|---|---|---|
delta | Number | 否 | 1 | 返回的页面数,如果 delta 大于现有页面数,则返回到首页。 | |
animationType | String | 否 | pop-out | 窗口关闭的动画效果,详见:窗口动画 | App |
animationDuration | Number | 否 | 300 | 窗口关闭动画的持续时间,单位为 ms | App |
示例
// 注意:调用 navigateTo 跳转时,调用该方法的页面会被加入堆栈,而 redirectTo 方法则不会。见下方示例代码
// 此处是A页面
uni.navigateTo({
url: 'B?id=1'
});
// 此处是B页面
uni.navigateTo({
url: 'C?id=1'
});
// 在C页面内 navigateBack,将返回A页面
uni.navigateBack({
delta: 2
});
EventChannel
2.8.9+ 支持 页面间事件通信通道
方法
EventChannel.emit(string eventName, any args)
触发一个事件
string eventName 事件名称
any args 事件参数
EventChannel.off(string eventName, function fn)
取消监听一个事件。给出第二个参数时,只取消给出的监听函数,否则取消所有监听函数
string eventName 事件名称
function fn 事件监听函数
参数 any args 触发事件参数
EventChannel.on(string eventName, function fn)
持续监听一个事件
string eventName 事件名称
function fn 事件监听函数
参数 any args 触发事件参数
EventChannel.once(string eventName, function fn)
监听一个事件一次,触发后失效
string eventName 事件名称
function fn 事件监听函数
参数 any args 触发事件参数
Tips:
navigateTo
, redirectTo
只能打开非 tabBar 页面。switchTab
只能打开 tabBar
页面。reLaunch
可以打开任意页面。tabBar
由页面决定,即只要是定义为 tabBar
的页面,底部都有 tabBar
。App.vue
里面进行页面跳转。navigateBack
不能返回,如果一定要返回可以使用history.back()
导航到浏览器的其他历史记录。参考事项
窗口动画
本API仅App支持。小程序自身不支持自定义动画。H5的窗体动画可使用常规单页动画处理方案,见H5下单页动画示例
窗口的显示/关闭动画效果,支持在 API、组件、pages.json 中配置,优先级为:API = 组件 > pages.json
。
API
有效的路由 API
uni.navigateTo({
url: '../test/test',
animationType: 'pop-in',
animationDuration: 200
});
uni.navigateBack({
delta: 1,
animationType: 'pop-out',
animationDuration: 200
});
组件
open-type 有效值
navigator
navigator
pages.json
pages.json 中配置的是窗口显示的动画
"style": {
"app-plus": {
"animationType": "fade-in",
"animationDuration": 300
}
}
显示动画与关闭动画,会有默认的对应规则。但是如果通过 API 或组件配置了窗口关闭的动画类型,则不会使用默认的类型。
显示动画 | 关闭动画 | 显示动画描述(关闭动画与之相反) |
---|---|---|
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 | 无动画 |
详细的窗口动画说明,请参考:
注意