自定义指令最省事,推荐新手用局部指令vFocus实现自动聚焦,支持原生input和el-input等封装组件,全局注册后全项目复用,比ref+mounted更简洁可靠。

直接用自定义指令最省事,写一次,到处能用,还不用反复操作 ref 或生命周期钩子。
用局部指令快速实现(推荐新手)
在 <script setup> 中定义一个以 v- 开头的变量,名字用驼峰式,模板里用短横线写法:
- 定义指令:const vFocus = { mounted: (el) => el.focus() };
- 模板使用:<input v-focus /> 或 <el-input v-focus />
- 注意:如果用的是 el-input 这类封装组件,它内部的 input 不是根元素,得加一层查找逻辑,比如 el.querySelector('input')?.focus()
适配 el-input 等封装组件的写法
原生 input 直接调用 el.focus() 就行,但 Element Plus 的 el-input 渲染后结构更复杂,真实输入框藏在内部:
- 安全做法是主动找 input 元素:const input = el.querySelector('input') || el.querySelector('.el-input__inner');
- 再调用 input?.focus(),避免报错
- 加上 requestAnimationFrame 更稳妥,确保浏览器有渲染机会:requestAnimationFrame(() => input?.focus())
全局注册,全项目复用
想让所有组件都能用 v-focus,就在应用初始化时全局注册:
立即学习“前端免费学习笔记(深入)”;
- main.js 或 main.ts 中:app.directive('focus', { mounted: (el) => { /* 同上查找逻辑 */ } })
- 之后任意组件中写 <input v-focus> 或 <el-input v-focus> 都能生效
- 不用每个组件都写指令定义,也不用重复绑 ref,维护成本低
为什么比 ref + mounted 更适合新手?
ref 方式要三步走:写 ref 属性 → 在 setup 或 options 里声明 ref → 在 mounted 里手动调 focus。稍一遗漏就失效;而指令把逻辑封装好了,只关注“我要聚焦”,不操心“怎么聚焦”:
- 指令自动感知元素挂载时机,不用手动等 DOM 渲染
- 没有 this.$refs、this.$nextTick 等概念负担
- 模板里一眼看出行为意图,语义清晰


















