Vite2生产环境下Vue3组合式API绑定的ref元素为undefined如何解决
问题根源
你的问题本质是自定义Hook的状态共享逻辑不规范,和Vite构建配置无关。
你当前将isShow、rootRef定义在Hook函数外部,属于模块级单例变量,理论上所有调用useShow的组件会共享同一份状态,但打包为库后出现实例不一致:
- 开发环境下Vite的模块缓存为严格单实例,多次导入同一模块只会初始化一次,因此
App.vue和HelloWorld.vue调用useShow拿到的是同一个rootRef,运行正常。 - 生产环境构建为库后,受引入方打包规则、树摇拆分逻辑影响,你的Hook模块可能被实例化两次,两个组件拿到的是独立的
rootRef实例,HelloWorld绑定的ref自然无法同步到App中调用的changeShow方法里,因此返回undefined。
解决方案
方案1:改用全局状态管理(推荐)
使用Pinia存储共享状态,无论多少组件调用,始终拿到同一份实例:
- 定义全局store:
// stores/show.ts import { defineStore } from 'pinia' export const useShowStore = defineStore('show', () => { const isShow = ref(false) const rootRef = ref<HTMLDivElement>() function changeShow() { isShow.value = !isShow.value console.log(isShow.value, rootRef.value) } return { isShow, rootRef, changeShow } })
- 在两个组件中统一调用store即可:
// App.vue / HelloWorld.vue 通用写法 import { useShowStore } from '@/stores/show' const { isShow, rootRef, changeShow } = useShowStore()
方案2:使用provide/inject传递实例
如果不想引入全局状态管理,可在父组件只初始化一次Hook实例,通过依赖注入传递给子组件:
- 先修正Hook的规范写法,将状态移到函数内部,避免模块级副作用:
// composables/useShow.ts export default function () { const isShow = ref(false) const rootRef = ref<HTMLDivElement>(); function changeShow() { isShow.value = !isShow.value; console.log(isShow.value, rootRef.value); } return { isShow, rootRef, changeShow }; }
- 在
App.vue中初始化实例并注入:
import { provide } from 'vue' import useShow from "./composables/useShow"; const showInstance = useShow() provide('showInstance', showInstance) const { changeShow } = showInstance
- 在
HelloWorld.vue中注入实例:
import { inject } from 'vue' const { rootRef, isShow } = inject<ReturnType<typeof useShow>>('showInstance')!
配置说明
你当前的Vite库打包配置符合规范,不需要修改,调整业务代码逻辑即可解决问题。
内容的提问来源于stack exchange,提问作者jeremyjone
相关产品推荐
相关产品推荐

