You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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存储共享状态,无论多少组件调用,始终拿到同一份实例:

  1. 定义全局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 }
})
  1. 在两个组件中统一调用store即可:
// App.vue / HelloWorld.vue 通用写法
import { useShowStore } from '@/stores/show'
const { isShow, rootRef, changeShow } = useShowStore()

方案2:使用provide/inject传递实例

如果不想引入全局状态管理,可在父组件只初始化一次Hook实例,通过依赖注入传递给子组件:

  1. 先修正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 };
}
  1. 在App.vue中初始化实例并注入:
import { provide } from 'vue'
import useShow from "./composables/useShow";

const showInstance = useShow()
provide('showInstance', showInstance)
const { changeShow } = showInstance
  1. 在HelloWorld.vue中注入实例:
import { inject } from 'vue'
const { rootRef, isShow } = inject<ReturnType<typeof useShow>>('showInstance')!

配置说明

你当前的Vite库打包配置符合规范,不需要修改,调整业务代码逻辑即可解决问题。

内容的提问来源于stack exchange,提问作者jeremyjone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 02:15:02