Vue3:如何将mixin的setup()中非响应式类实例传递给组件
Vue 3 中传递非响应式类实例 Mixin 的解决方案
问题背景
需要将基于 JavaScript 类的对象通过 Mixin 传递给组件,且不能具备响应式特性。由于使用 TypeScript,若不在 data() 中声明类型,无法将对象赋值给 Mixin 的 this,但 data() 的响应式处理会破坏原有对象结构。
初始代码示例
Mixin 文件(mixin.js):
export default { setup() { const foo = new Foo() return { foo, } } }
组件文件(component.js):
import mixin from './mixin.js' export default { setup() { // 如何在此处获取 foo? } }
更新需求
上述方案仅适用于全局共享一个 foo 实例的场景,现在需要实现每个组件拥有独立的 foo 实例,效果类似 JavaScript 类继承:
class Mixin { foo() { // ... } } class Component extends Mixin { bar() { this.foo() } }
解决方案
1. 获取全局共享的 Mixin 实例(初始问题)
在 Vue 3 的 Composition API 中,组件注入 Mixin 后,setup 返回的属性会自动注入组件上下文。可通过 getCurrentInstance 获取组件实例,进而拿到非响应式的 foo:
// component.js import { getCurrentInstance } from 'vue' import mixin from './mixin.js' export default { mixins: [mixin], // 先注入 Mixin setup() { const instance = getCurrentInstance() const foo = instance?.proxy?.foo // 拿到非响应式的 foo 实例 // 后续直接使用 foo 即可 } }
TypeScript 环境下,可手动给 foo 声明类型,无需依赖 data() 的响应式绑定来获取类型提示。
2. 实现每个组件独立的类实例(更新需求)
放弃传统 Options API 的 Mixin,改用组合式函数(Composable) 实现类继承式的独立实例效果,每次调用函数都会创建新的类实例:
第一步:编写组合式函数
// useFoo.js export function useFoo() { const foo = new Foo() // 每次调用都会生成新实例 return { foo } }
第二步:在组件中使用
// component.js import { useFoo } from './useFoo.js' export default { setup() { const { foo } = useFoo() // 每个组件都拿到独立的 foo 实例 // 直接使用 foo,无响应式干扰 return { foo } } }
TypeScript 类型支持
给 Foo 类定义类型后,组合式函数会自动推导返回值类型,无需额外配置:
// Foo.ts export class Foo { sayHello() { console.log('Hello from Foo instance') } } // useFoo.ts import { Foo } from './Foo.ts' export function useFoo() { const foo = new Foo() return { foo } } // component.ts import { useFoo } from './useFoo.ts' export default { setup() { const { foo } = useFoo() foo.sayHello() // 自动获得类型提示 return { foo } } }
这种方式既满足了组件实例隔离的需求,又避免了响应式对类对象的破坏,同时完美适配 TypeScript 类型检查。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

