在 `.ts` 文件中使用 `useQuasar()` 来获取 `$q` 实例,是 Quasar 框架开发中的常见需求
在 `.ts` 文件中使用 `useQuasar()` 来获取 `$q` 实例,是 Quasar 框架开发中的常见需求。`$q` 对象提供了访问 Quasar 的各种插件(如通知、对话框、加载条等)、屏幕尺寸信息以及国际化等功能。
由于 `useQuasar` 是一个 **Vue composable**,它必须在 **Vue 组件的 `setup()` 函数**或 **一个生命周期钩子**中调用。如果你的 `.ts` 文件不是一个 Vue 组件,就需要通过其他方式获取 `$q`。
以下是几种方法及其适用场景:
| 场景分类 | 推荐方法 | 关键要点 |
| :--- | :--- | :--- |
| **在 Vue 组件内** | 直接使用 `useQuasar` Composables | 确保在 `setup()` 或 `<script setup>` 中调用 |
| **在非 Vue 组件的外部 TS 文件** | 导入已初始化的 `$q` 对象 | 需通过应用实例传递或导出 `$q` |
| **在 Quasar Boot 文件** | 使用 `boot` 函数参数 | 通过 `ctx.app.config.globalProperties.$q` 访问 |
| **需要类型支持** | 扩展 Vue 类型定义 | 创建 `src/shims-vue.d.ts` 文件增强类型 |
### 🛠 方法一:在 Vue 组件或 Composables 中使用
这是最直接和推荐的方式。只需在你的 Vue 组件的 `<script setup>` 或 `setup()` 函数中调用 `useQuasar()`。
```typescript
// 在 Composition API 组件中 (<script setup>)
import { useQuasar } from 'quasar'
// 必须在 setup 上下文中调用
const $q = useQuasar()
// 现在你可以使用 $q 了
$q.notify('这是一个通知消息') // 示例:显示一个通知
```
```typescript
// 在 Options API 组件中 (如果你使用了 setup 函数)
import { useQuasar } from 'quasar'
import { defineComponent } from 'vue'
export default defineComponent({
setup () {
const $q = useQuasar()
// 使用 $q
$q.notify('在 Options API 的 setup 中使用')
// 如果需要,可以 return { $q } 以在模板中使用
}
})
```
### 📁 方法二:在外部 .ts 文件中使用(需要注入)
如果你的纯 TypeScript 文件需要频繁使用 `$q`,一个较好的模式是在应用初始化时**将 `$q` 对象作为一个参数或依赖项传递**给你的外部函数模块。
1. **首先,在你的 Vue 组件或应用入口中获取 `$q`:**
```typescript
// 某个Vue组件
import { useQuasar } from 'quasar'
import { someUtilityFunction } from '@/utils/myUtility' // 导入外部工具函数
const $q = useQuasar()
// 调用外部函数,并传入 $q 对象
someUtilityFunction($q)
```
2. **然后,在你的外部 .ts 文件中接收并使用它:**
```typescript
// @/utils/myUtility.ts
import { QVueGlobals } from 'quasar' // 导入类型
export function someUtilityFunction($q: QVueGlobals) {
// 现在你可以安全地使用 $q 了
$q.notify('这个通知来自外部的工具函数!')
if ($q.screen.lt.sm) {
console.log('当前是小屏幕设备')
}
}
```
这种方式**显式地传递依赖**,使得你的函数更加清晰和可测试。
### 🚀 方法三:在 Quasar Boot 文件中使用
Quasar 的 **Boot 文件**是应用启动时运行的脚本,是初始化一些全局设置或库的理想场所。`boot` 文件的参数提供了访问 `$q` 的途径。
```typescript
// src/boot/your-boot-file.ts
// 注意:boot 文件默认使用 .ts 后缀,Quasar CLI 已配置好 TypeScript 支持
import { Boot } from 'quasar/wrappers'
// 通过 "boot" 包装器定义
export default Boot(({ app, store, ssrContext }) => {
// 这里无法直接使用 useQuasar(),因为它也是一个 composable
// 但我们可以通过 app 实例来访问全局属性
const $q = app.config.globalProperties.$q
// 使用 $q
$q.notify('这是在 boot 文件中发出的通知')
})
```
记得在 `quasar.conf.js` 中注册你的 boot 文件:
```javascript
// quasar.conf.js
module.exports = function (ctx) {
return {
boot: [
'your-boot-file' // 你的 boot 文件名
],
// ...
}
}
```
### 🔧 方法四:获取当前应用实例的 $q
在极少数情况下,你可能需要在一个非常偏僻的地方获取 `$q`,并且无法通过参数传递。这时,你可以尝试从当前活动的 Vue 应用实例中获取。
```typescript
// 在某些深入的第三方库集成中可能会用到
import { getCurrentInstance } from 'vue'
export function someAdvancedFunction() {
// 获取当前组件实例
const instance = getCurrentInstance()
// 如果存在当前实例,则可以从全局属性中获取 $q
// 需要谨慎使用,因为它可能为 null 或 undefined
const $q = instance?.appContext.config.globalProperties.$q
if ($q) {
$q.notify('从当前实例中获取到了 $q')
} else {
console.error('无法获取 $q 实例')
}
}
```
**注意:** 这种方法**不确定性较高**,强烈建议优先使用前面提到的依赖注入(方法二)或 Composables(方法一)的方式。
### 📌 为外部使用提供 $q 的实用函数
你可以创建一个专门的文件来提供 `$q` 实例。
1. **创建一个工具文件** (例如 `quasar-instance.ts`):
```typescript
// src/utils/quasar-instance.ts
import { QVueGlobals } from 'quasar'
// 创建一个变量来保存 $q 的引用
let $qInstance: QVueGlobals | null = null
// 提供一个设置函数,在应用启动时调用
export function setQuasarInstance(instance: QVueGlobals) {
$qInstance = instance
}
// 提供一个获取函数
export function getQuasarInstance(): QVueGlobals {
if (!$qInstance) {
throw new Error('Quasar 实例尚未初始化。请确保在应用启动时调用了 setQuasarInstance。')
}
return $qInstance
}
```
2. **在应用入口处设置实例** (例如 `App.vue`):
```typescript
// src/App.vue
<script setup lang="ts">
import { useQuasar } from 'quasar'
import { setQuasarInstance } from '@/utils/quasar-instance'
const $q = useQuasar()
// 设置全局实例
setQuasarInstance($q)
</script>
<template>
<router-view />
</template>
```
3. **在任何外部 .ts 文件中使用**:
```typescript
// @/services/some-api-service.ts
import { getQuasarInstance } from '@/utils/quasar-instance'
export function handleApiError(error: unknown) {
const $q = getQuasarInstance()
const message = error instanceof Error ? error.message : '发生未知错误'
$q.notify({
type: 'negative',
message: `请求失败: ${message}`,
position: 'top'
})
}
```
### 🧰 增强 TypeScript 支持
为了在所有地方获得最好的 TypeScript 类型提示,你可以在项目中创建一个类型声明文件(例如 `src/shims-vue.d.ts`),来扩展 Vue 的全局属性接口。
```typescript
// src/shims-vue.d.ts
import { QVueGlobals } from 'quasar'
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$q: QVueGlobals;
}
}
```
完成此操作后,在 Vue 模板和组件上下文中使用 `this.$q` 时,TypeScript 就能识别其类型了。
### ⚠️ 注意事项
1. **执行上下文**:`useQuasar()` 必须在 Vue 的 `setup()` 生命周期或同步的 Composables 中调用。在普通的 `.ts` 文件(非 Vue 组件或 Composables)中直接调用 `useQuasar()` **会失败**并可能抛出错误,提示 "getCurrentInstance" 为 `null`。
2. **Boot 文件中的区别**:在 Quasar 的 boot 文件中,应使用 `Boot` 函数参数中提供的 `app` 实例来访问全局属性,而不是使用 `useQuasar()` composable。
3. **SSR 考虑**:在服务端渲染 (SSR) 模式下,一些基于 DOM 的插件属性(如 `$q.cookies`)可能不可用,使用时需要注意检查。
希望这些解释和示例能帮助你在不同类型的 `.ts` 文件中有效地使用 `$q` 对象。
浙公网安备 33010602011771号