Vue 3组合式函数中获取DOM需组件层创建ref并传入,composable仅消费且须判空;生命周期钩子如onMounted必须由组件调用,不可在composable内直接使用。

在 Vue 3 组合式函数(composable)中用 ref 获取 DOM 元素,核心原则不变:DOM 尚未挂载时 ref.value 一定是 null,必须等挂载完成才能安全访问。但组合式函数本身不直接参与生命周期钩子,所以需要把生命周期依赖显式暴露或注入。
组合式函数里必须接收 onMounted 或 useOnMounted
不能在 composable 内部直接调用 onMounted(它属于组件上下文),而应由调用方传入,或通过参数提供执行时机:
- 推荐方式:让组合式函数接受一个回调,在合适的时机触发
- 例如:
useDomFocus(elRef, { onMounted }),内部只做逻辑,不控制时机 - 也可返回一个函数(如
setupDomAction),由组件在onMounted中调用
ref 必须由组件层创建并传递进去
组合式函数不负责声明 ref,而是消费它:
- 组件中定义
const inputRef = ref(null),再传给 composable - composable 内部只读取
elRef.value,且必须先判空(即使在 onMounted 后也建议防御性检查) - 命名需严格一致:模板中
ref="inputRef"↔ 组件中const inputRef = ref(null)↔ 传入 composable 的参数名也建议一致
常见错误写法要避开
以下操作在组合式函数中是无效或危险的:
立即学习“前端免费学习笔记(深入)”;
- 在 composable 内部直接写
console.log(inputRef.value)—— 此时大概率是null - 试图在 composable 里调用
onMounted(() => {...})—— 会报错或行为不可预期,因缺少当前组件实例上下文 - 用字符串 ref(如
ref="input")配合getCurrentInstance().refs.input—— 已被废弃,且破坏响应式和类型推导
一个可复用的聚焦示例
比如封装一个自动聚焦输入框的组合式函数:
<pre class="brush:php;toolbar:false;">// composables/useAutoFocus.ts
import { Ref, onMounted } from 'vue'
export function useAutoFocus(elRef: Ref<HTMLElement | null>) {
const focus = () => {
if (elRef.value) {
elRef.value.focus()
}
}
// 不在此处调用 focus,只暴露方法
return { focus }
}
// 在组件中使用:
// <script setup>
// import { ref, onMounted } from 'vue'
// import { useAutoFocus } from '@/composables/useAutoFocus'
//
// const inputRef = ref<HTMLInputElement | null>(null)
// const { focus } = useAutoFocus(inputRef)
//
// onMounted(() => {
// focus()
// })
// </script>
//
// <template>
// <input ref="inputRef" />
// </template>


















