- 示例工程
- 前端
- 移动开发
- 跨平台
【免费下载链接】uni-app
A cross-platform framework using Vue.js
getApp()是 uni-app x 中获取当前应用实例的核心 API,通过它可以在任意页面或 uts 插件中访问App.uvue暴露的全局方法与全局数据。本文以 docs/api/get-app.md 为骨架,结合当前仓库中 App.uvue、store/index.uts 及 hello-uvue 示例工程 的源码实现,系统讲解getApp()的返回值结构、HBuilderX 4.31 前后的行为差异、UniApp对象上各属性与方法的能力边界,并给出可直接运行的完整实战示例。读完本文,你将掌握通过getApp().vm调用 App 全局方法、通过getApp().globalData读写全局数据的标准姿势,以及 Android 原生上下文、鸿蒙 Ability 获取和整应用重启等进阶能力。
getApp() 的作用与演进
getApp()函数用于获取当前应用实例,通过该实例可以调用App.uvue中methods里定义的方法(详见下文"全局方法调用"一节)。
自 HBuilderX 4.31 起,该 API 的行为发生了重要变化,理解这段演进是正确使用它的前提:
- HBuilderX 4.31 以前:
getApp()返回的是 Vue 实例,且无法在 uts 插件中使用。 - HBuilderX 4.31+:新增
UniApp对象用于管理 app,getApp()返回UniApp对象;原来的 Vue 实例则作为UniApp对象的vm属性提供。
这一设计的核心动机是:UniApp对象可在 uts 插件和 uvue 页面中同时使用,但vm属性及其相关的globalData仍然只能在 uvue 页面中使用。换言之,getApp()在 uts 插件里拿到的只是不依赖 Vue 运行时的原生层应用对象,而页面中才能进一步触达 Vue 实例层。
从仓库源码可以印证这套分层结构:hello-uvue 示例的 index 页面 中的自动化测试同时使用了两种访问路径:
const checkGlobalData = () : boolean => { const app = getApp() const globalData = app.globalData // 直接访问 UniApp.globalData return globalData.str == 'globalData str' && globalData.num == 1 && globalData.boolean } const checkLaunchPath = () : boolean => { const app = getApp() return app.vm!.checkLaunchPath() // 通过 vm 调用 App.uvue 暴露的方法 }使用限制
getApp()只能在script中调用,不能直接在模板中使用。若在模板表达式里需要应用实例数据,应先在<script>中取值再绑定到页面响应式状态。UniApp对象可同时在 uts 插件和 uvue 页面中使用;vm属性及其相关的globalData仍然只能在 uvue 页面中使用。
getApp 兼容性
getApp()本身及各能力在不同平台上的支持情况如下("√"表示支持,"x"表示不支持,数字表示支持的 HBuilderX 版本号):
| Web | 微信小程序 | Android | Android(Vapor) UTS 插件 | iOS | iOS(VDOM) UTS 插件 | iOS(Vapor) UTS 插件 | HarmonyOS | | :- | :- | :- | :- | :- | :- | :- | :- | | 4.0 | √ | √ | x | √ | 4.31 | x | 4.61 |
可以看到,getApp()在 Web、微信小程序、Android、iOS 及 HarmonyOS(4.61)等主流平台上均可用,而 Vapor 渲染引擎的 UTS 插件场景目前尚未支持。
返回值:UniApp 对象
getApp()的返回类型为 UniApp。
UniApp 的属性描述
| 名称 | 类型 | 必备 | 兼容性 | 描述 | | :- | :- | :- | :-: | :- | | vm | ComponentPublicInstance | 否 | Web: 4.31; 微信小程序: x; Android: 4.31; Android(Vapor) UTS 插件: x; iOS: 4.31; iOS UTS 插件: x; HarmonyOS: 4.61 | App vue 实例对象 | | globalData | Record<K, T> | 是 | Web: 4.31; 微信小程序: x; Android: 4.31; Android(Vapor) UTS 插件: x; iOS: 4.31; iOS(Vapor) UTS 插件: x; HarmonyOS: 4.61 | 全局对象 | |$vm| ComponentPublicInstance | 否 | Web: 4.31; 微信小程序: x; Android: 4.31; Android(Vapor) UTS 插件: x; iOS: 4.31; iOS UTS 插件: x; HarmonyOS: 4.61 | App vue 实例对象,已废弃,仅为了向下兼容保留|
要点解读:
globalData为必选属性,是存放应用级全局数据的容器;vm与$vm为可选属性。vm与废弃的$vm指向同一 App Vue 实例,新代码统一使用vm;$vm的存在只是为了旧代码平滑迁移。ComponentPublicInstance对应选项式 API 中的组件实例类型,可参考 选项式 API 文档 中的定义。- 在微信小程序端
vm/$vm/globalData均为 x(不支持),这是 uni-app x 与原生微信小程序框架在应用实例模型上的差异点,跨端开发时需注意。
从源码看 globalData 的典型组织方式
在当前仓库的 src/store/index.uts 中,GlobalData被定义为一个覆盖多种数据类型的结构,可作为定义自己globalData的模板:
export type GlobalData = { str: string num: number bool: boolean obj: UTSJSONObject null: string | null arr: number[] set: Set<string> map: Map<string, any> fun: () => string launchOptions: OnLaunchOptions showOptions: OnShowOptions }对应的初始化在 同文件的 state 定义 中,并提供了updateGlobalData(key, value)方法按 key 更新各字段(src/store/index.uts#L188-L224)。这种"类型定义 + 集中初始化 + 按 key 更新"的模式,既保证了类型安全,也便于在App.uvue与页面之间共享。
另外,hello-uvue 工程的 App.uvue 演示了另一种声明方式——通过defineOptions直接声明globalData:
defineOptions({ globalData: { str: 'globalData str', num: 1, boolean: true } })两种方式殊途同归:页面里都可以用getApp().globalData读取,例如上文checkGlobalData测试所验证的globalData.str == 'globalData str' && globalData.num == 1 && globalData.boolean。
UniApp 的方法
UniApp对象除了属性外,还提供了几个面向原生能力的方法,均可在 uts 插件与 uvue 页面中使用。
getAndroidApplication(): Application
获取 Android 应用Application上下文。
兼容性:
| Web | 微信小程序 | Android(VDOM) | Android(Vapor) | iOS | HarmonyOS | | :- | :- | :- | :- | :- | :- | | x | x | 4.31 | x | x | x |
返回值:Application(Android 应用上下文对象)。
该方法的典型用途是在页面中获取 Android 原生上下文以调用原生 API。示例(来自 docs/api/get-app.md 的完整示例代码,运行于 Android 且非 Vapor 引擎时):
// #ifdef APP-ANDROID && !VUE3-VAPOR const getAndroidApplication = () : boolean => { const app = getApp() data.androidApplication = app.getAndroidApplication() return data.androidApplication !== null } // #endif注意示例代码用条件编译APP-ANDROID && !VUE3-VAPOR限定平台,与兼容性表格中"仅 Android(VDOM) 4.31 支持"完全对应。
getHarmonyAbility(): UIAbility
获取鸿蒙应用Ability实例(对应 HarmonyOS 的 UIAbility,即应用入口能力)。
兼容性:
| Web | 微信小程序 | Android | iOS | HarmonyOS(VDOM) | HarmonyOS(Vapor) | | :- | :- | :- | :- | :- | :- | | x | x | x | x | 4.61 | x |
返回值:UIAbility(鸿蒙 Ability 实例)。
仅在 HarmonyOS(VDOM) 且 HBuilderX 4.61+ 可用,在 uts 插件中获取后可用于访问鸿蒙侧的原生能力。
restart(url?: string): void
重启应用。
兼容性:
| Web | 微信小程序 | Android(VDOM) | Android(Vapor) | iOS(VDOM) | iOS(Vapor) | HarmonyOS | | :- | :- | :- | :- | :- | :- | :- | | x | x | x | 5.31 | x | 5.31 | x |
参数:
| 名称 | 类型 | 必填 | 兼容性 | 描述 | | :- | :- | :- | :-: | :- | | url | string | 否 | Web: x; 微信小程序: x; HarmonyOS: x | 重启后打开的页面地址 |
restart()目前仅在 iOS(VDOM)、iOS(Vapor) 的 5.31+ 版本可用,可传入url指定重启后要打开的页面;Web、微信小程序、HarmonyOS 不支持该能力。
完整示例:读写 globalData 与调用 App 全局方法
以下完整示例来自 docs/api/get-app.md,对应官方演示工程的 get-app 页面。它演示了getApp()的三个核心用法:读取globalData、更新globalData、通过vm调用App.uvue中定义的方法(并配合 src/store/index.uts 的updateGlobalData实现数据更新):
<template> <!-- #ifdef APP --> <scroll-view style="flex: 1; padding-bottom: 20px"> <!-- #endif --> <view style="padding-bottom: 20px"> <page-head title="getApp"></page-head> <view class="uni-padding-wrap"> <button @click="getGlobalData">get globalData</button> <template v-if="data.originGlobalData.str.length"> <text class="uni-common-mt bold">初始的 globalData:</text> <text class="uni-common-mt">globalData string: {{ data.originGlobalData.str }}</text> <text class="uni-common-mt">globalData number: {{ data.originGlobalData.num }}</text> <text class="uni-common-mt">globalData boolean: {{ data.originGlobalData.bool }}</text> <text class="uni-common-mt">globalData object: {{ data.originGlobalData.obj }}</text> <text class="uni-common-mt">globalData null: {{ data.originGlobalData.null }}</text> <text class="uni-common-mt">globalData array: {{ data.originGlobalData.arr }}</text> <text class="uni-common-mt">globalData Set: {{ data.originGlobalData.set }}</text> <text class="uni-common-mt">globalData Map: {{ data.originGlobalData.map }}</text> <text class="uni-common-mt">globalData fun 返回值: {{ data.originGlobalDataFuncRes }}</text> </template> <button @click="setGlobalData" class="uni-common-mt"> set globalData </button> <template v-if="data.newGlobalData.bool"> <text class="uni-common-mt bold">更新后的 globalData:</text> <text class="uni-common-mt">globalData string: {{ data.newGlobalData.str }}</text> <text class="uni-common-mt">globalData number: {{ data.newGlobalData.num }}</text> <text class="uni-common-mt">globalData boolean: {{ data.newGlobalData.bool }}</text> <text class="uni-common-mt">globalData object: {{ data.newGlobalData.obj }}</text> <text class="uni-common-mt">globalData null: {{ data.newGlobalData.null }}</text> <text class="uni-common-mt">globalData array: {{ data.newGlobalData.arr }}</text> <text class="uni-common-mt">globalData Set: {{ data.newGlobalData.set }}</text> <text class="uni-common-mt">globalData Map: {{ data.newGlobalData.map }}</text> <text class="uni-common-mt">globalData fun 返回值: {{ data.newGlobalDataFuncRes }}</text> </template> <text class="uni-common-mt">点击按钮调用 App.uvue methods</text> <text class="uni-common-mt">increaseLifeCycleNum 方法</text> <button class="uni-common-mt" @click="_increaseLifeCycleNum"> increase lifeCycleNum </button> <text class="uni-common-mt">lifeCycleNum: {{ data.lifeCycleNum }}</text> <!-- #ifdef APP-ANDROID && !VUE3-VAPOR --> <button class="uni-common-mt" @click="getAndroidApplication"> getAndroidApplication </button> <text class="uni-common-mt">androidApplication is null: {{ data.androidApplication == null }}</text> <!-- #endif --> </view> </view> <!-- #ifdef APP --> </scroll-view> <!-- #endif --> </template> <script setup lang="uts"> import { state, setLifeCycleNum, updateGlobalData } from '@/store/index.uts' type MyGlobalData = { str : string, num : number, bool : boolean, obj : UTSJSONObject, null : string | null, arr : number[], set : string[], map : UTSJSONObject, fun : () => string } type DataType = { originGlobalData: MyGlobalData; originGlobalDataFuncRes: string; newGlobalData: MyGlobalData; newGlobalDataFuncRes: string; lifeCycleNum: number; androidApplication: any | null; } const data = reactive({ originGlobalData: { str: '', num: 0, bool: false, obj: { str: '', num: 0, bool: false }, null: null, arr: [] as number[], set: [] as string[], map: {}, fun: () : string => '' }, originGlobalDataFuncRes: '', newGlobalData: { str: '', num: 0, bool: false, obj: { str: '', num: 0, bool: false }, null: null, arr: [] as number[], set: [] as string[], map: {}, fun: () : string => '' }, newGlobalDataFuncRes: '', lifeCycleNum: 0, androidApplication: null } as DataType) const getGlobalData = () => { data.originGlobalData.str = state.globalData.str data.originGlobalData.num = state.globalData.num data.originGlobalData.bool = state.globalData.bool data.originGlobalData.obj = state.globalData.obj data.originGlobalData.null = state.globalData.null data.originGlobalData.arr = state.globalData.arr state.globalData.set.forEach((value : string) => { data.originGlobalData.set.push(value) }) state.globalData.map.forEach((value : any, key : string) => { data.originGlobalData.map[key] = value }) data.originGlobalData.fun = state.globalData.fun data.originGlobalDataFuncRes = data.originGlobalData.fun() } const setGlobalData = () => { updateGlobalData('str', 'new globalData str') updateGlobalData('num', 100) updateGlobalData('bool', true) updateGlobalData('obj',{ str: 'new globalData obj str', num: 200, bool: true }) updateGlobalData('null', 'not null') updateGlobalData('arr', [1, 2, 3]) updateGlobalData('set', new Set(['a', 'b', 'c'])) updateGlobalData('map', new Map<string, any>([ ['a', 1], ['b', 2], ['c', 3] ])) updateGlobalData('fun', () : string => { return 'new globalData fun' }) data.newGlobalData.str = state.globalData.str data.newGlobalData.num = state.globalData.num data.newGlobalData.bool = state.globalData.bool data.newGlobalData.obj = state.globalData.obj data.newGlobalData.null = state.globalData.null data.newGlobalData.arr = state.globalData.arr console.log('state.globalData.arr',state.globalData.arr) console.log('state.globalData.set',state.globalData.set) state.globalData.set.forEach((value : string) => { data.newGlobalData.set.push(value) }) state.globalData.map.forEach((value : any, key : string) => { data.newGlobalData.map[key] = value }) data.newGlobalData.fun = state.globalData.fun data.newGlobalDataFuncRes = data.newGlobalData.fun() } const _increaseLifeCycleNum = () => { const app = getApp() app.vm!.increaseLifeCycleNum() data.lifeCycleNum = state.lifeCycleNum } // 自动化测试 const setLifeCycleNumFunc = (num : number) => { setLifeCycleNum(num) } // #ifdef APP-ANDROID && !VUE3-VAPOR const getAndroidApplication = () : boolean => { const app = getApp() data.androidApplication = app.getAndroidApplication() return data.androidApplication !== null } // #endif onReady(() => { data.lifeCycleNum = state.lifeCycleNum }) defineExpose({ data, getGlobalData, setGlobalData, _increaseLifeCycleNum, setLifeCycleNumFunc, // #ifdef APP-ANDROID && !VUE3-VAPOR getAndroidApplication // #endif }) </script> <style> .bold { font-weight: bold; } .hr { border-bottom: 1px solid #ccc; } </style>示例要点拆解:
_increaseLifeCycleNum中app.vm!.increaseLifeCycleNum()即"通过getApp()调用App.uvue中定义的全局方法"的标准写法,非空断言!表示信任vm一定存在(页面环境满足该前提)。- 该示例对应本仓库 src/App.uvue 中
increaseLifeCycleNum的定义与导出:
const increaseLifeCycleNum = () => { setLifeCycleNum(state.lifeCycleNum + 100) console.log('App increaseLifeCycleNum') } defineExpose({ increaseLifeCycleNum, })updateGlobalData的实现见 src/store/index.uts#L188-L224,它通过 switch 按 key 对globalData各字段赋值,并支持Set、Map、函数等复杂类型。
全局方法调用(@appmethods)
上文的示例中,getApp()后调用了App.uvue里定义的increaseLifeCycleNum方法。在 HBuilderX 4.31 中getApp()返回值调整为UniApp类型后,调用App.uvue中定义的全局方法需要做如下调整:
| 版本 | 调用方式 | | :- | :- | | 4.31 之前 |getApp().methodName()| | 4.31 及之后 |getApp().vm?.methodName()|
即必须经由vm属性才能触达 App Vue 实例上暴露的方法。仓库示例工程中同样遵循这一写法,例如 hello-uvue 的 App.uvue 在onAppShow中通过getApp()?.vm?.globalPropertiesStr读取全局属性,index 页面 通过app.vm!.checkLaunchPath()与app.vm!.checkAppMixin()调用 App 暴露的测试方法。
配套的App.uvue侧需要将方法通过defineExpose暴露出去(见 src/App.uvue#L181-L183),页面侧才能通过vm调用;如果App.uvue中没有defineExpose,则相应方法对外不可见。
结合源码的纵深解读:调用链与数据流
把文档、示例与仓库源码串起来,可以梳理出getApp()相关的完整调用链:
- 应用启动:
App.uvue的onLaunch被触发(src/App.uvue#L8-L57),其中把启动参数写入globalData.launchOptions,并调用checkSystemTheme()等初始化逻辑。 - 数据初始化:
globalData的初始值在 src/store/index.uts#L70-L93 的state中统一声明(字符串、数字、布尔、UTSJSONObject、数组、Set、Map、函数、启动参数等),页面与App.uvue共享同一个state单例。 - 页面访问:任意页面
const app = getApp()拿到UniApp对象,直接读app.globalData,或通过app.vm!.xxx()调用App.uvue用defineExpose暴露的全局方法。 - 数据更新:通过
updateGlobalData(key, value)修改globalData后,页面读取到的数据同步更新;示例中setGlobalData里还通过state.globalData.set.forEach、state.globalData.map.forEach遍历Set/Map后回填到本地响应式数据。 - 原生能力:需要 Android
Application或鸿蒙UIAbility时,分别调用app.getAndroidApplication()(仅 Android(VDOM))与app.getHarmonyAbility()(仅 HarmonyOS(VDOM)),实现从 uni-app x 业务层触达原生层。
这一数据流与调用链在 examples/hello-uvue 工程中有完整实现可供对照阅读:入口 App.uvue、首页 pages/index/index.uvue 中的checkGlobalData、checkLaunchPath、checkAppMixin三个自动化测试方法即是对上述三条访问路径的运行时验证。
通用类型:GeneralCallbackResult
getApp()相关文档末尾还给出了一个通用回调结果类型定义:
| 名称 | 类型 | 必备 | 描述 | | :- | :- | :- | :- | | errMsg | string | 是 | 错误信息 |
该类型是 uni-app x 中各类异步 API 回调结果的基础类型,统一通过errMsg字段描述错误信息,在接口统一性与错误处理规范中广泛复用。
总结与最佳实践
围绕getApp(),可以沉淀出以下实践建议:
- 优先访问
globalData:跨页面、跨模块共享的应用级数据放在globalData中,页面侧通过getApp().globalData.xxx读取;对Set、Map等容器类型,遍历后再回填到页面本地数据(参考示例中的写法),避免直接引用造成的响应式问题。 - 调用 App 全局方法必须走
vm:HBuilderX 4.31+ 一律使用getApp().vm?.methodName()(或app.vm!.methodName()),并在App.uvue中通过defineExpose显式暴露;旧代码中getApp().methodName()的写法需要迁移。 - 留意平台差异:
vm/globalData在微信小程序端不可用;getAndroidApplication()仅 Android(VDOM);getHarmonyAbility()仅 HarmonyOS(VDOM) 4.61+;restart()仅 iOS 5.31+。涉及这些能力的代码建议用条件编译包裹。 - 仅限 script 中使用:
getApp()不能出现在模板中,模板需要的数据提前在<script setup>中取出存入响应式变量。 - 废弃属性不复用:
$vm仅为向下兼容保留,新代码统一使用vm。
- 示例工程
- 前端
- 移动开发
- 跨平台
【免费下载链接】uni-app
A cross-platform framework using Vue.js
相关推荐
uni-app x App.uvue 主组件完全指南:应用生命周期、globalData 全局变量、全局方法与全局样式
uni app x App.uvue 主组件完全指南:应用生命周期、globalData 全局变量、全局方法与全局样式 App.uvue 是 uni app x
示例工程前端移动开发跨平台uni-app x 全局变量与状态管理实战:globalData、Pinia 与全局 reactive 变量
uni app x 全局变量与状态管理实战:globalData、Pinia 与全局 reactive 变量 导读 本文围绕 uni app x 的全局数据共享
示例工程前端移动开发跨平台uni-app x UTS 内置对象 Uint16Array 完全指南:构造、属性与全部实例方法详解
uni app x UTS 内置对象 Uint16Array 完全指南:构造、属性与全部实例方法详解 本篇指南系统讲解 uni app x 的 UTS 语言中内
示例工程前端移动开发跨平台
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考