vue3:触发自动el-input输入框焦点

问:

怎么自动触发el-input输入框焦点

回答:

方法一:使用 nextTick + 组件暴露的 focus 方法(推荐)

复制代码
import { nextTick } from 'vue';

onMounted(async () => {
  await nextTick(); // 等待DOM更新完成
  
  if (searchInputRef.value) {
    searchInputRef.value.focus();
  }
});

方法二:使用 watch + nextTick(更保险)

复制代码
import { watch, nextTick } from 'vue';

// 监听组件是否已经挂载并准备好
watch(
  () => searchInputRef.value,
  (newVal) => {
    if (newVal) {
      nextTick(() => {
        newVal.focus();
      });
    }
  },
  { immediate: true } // 立即执行一次
);

方法三:使用自定义指令(最优雅)

复制代码
// 全局或局部注册指令
const vFocus = {
  mounted(el, binding) {
    const input = el.querySelector('input') || el.querySelector('.el-input__inner');
    if (input) {
      // 使用 requestAnimationFrame 确保在浏览器渲染周期内执行
      requestAnimationFrame(() => {
        input.focus();
      });
    }
  }
};

// 在模板中使用
<el-input
  v-focus
  ref="searchInputRef"
  // ...其他属性
>
</el-input>

方法四:使用 Intersection Observer(适用于需要滚动的场景)

复制代码
onMounted(() => {
  if (!searchInputRef.value) return;

  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        nextTick(() => {
          searchInputRef.value.focus();
        });
        observer.disconnect(); // 执行一次后断开观察
      }
    });
  });

  observer.observe(searchInputRef.value.$el);
});

方法五:组合式函数(最可复用)

复制代码
// 创建 useAutoFocus.js
import { ref, onMounted, nextTick } from 'vue';

export function useAutoFocus() {
  const targetRef = ref(null);
  
  const focus = async () => {
    await nextTick();
    if (targetRef.value) {
      targetRef.value.focus();
    }
  };

  onMounted(focus);

  return {
    targetRef,
    focus
  };
}

// 在组件中使用
import { useAutoFocus } from './useAutoFocus';

const { targetRef: searchInputRef } = useAutoFocus();

方法六:使用 Promise 和 requestAnimationFrame(最保险)

复制代码
onMounted(() => {
  const focusInput = () => {
    return new Promise((resolve) => {
      requestAnimationFrame(() => {
        if (searchInputRef.value) {
          searchInputRef.value.focus();
          resolve(true);
        } else {
          resolve(false);
        }
      });
    });
  };

  // 尝试多次,直到成功
  const tryFocus = async (maxAttempts = 5) => {
    for (let i = 0; i < maxAttempts; i++) {
      const success = await focusInput();
      if (success) break;
      await new Promise(resolve => setTimeout(resolve, 50)); // 短暂延迟
    }
  };

  tryFocus();
});

推荐方案

最推荐使用第一种方法(nextTick),因为:

  1. 官方推荐 :Vue 内置的 nextTick 是处理DOM更新后操作的标准方式

  2. 性能更好 :比 setTimeout 更高效

  3. 更可靠:确保在组件完全渲染后才执行焦点设置

  4. 代码简洁:不需要猜测延迟时间

复制代码
// 最佳实践
onMounted(async () => {
  await nextTick();
  searchInputRef.value?.focus();
});

这样既避免了 setTimeout 的不确定性,又保证了代码的可靠性和可维护性

相关推荐
等咸鱼的狸猫7 分钟前
JavaScript 隐式类型转换:从入门到精通
javascript
kyriewen2 小时前
我用 Codex 重写了同事维护三年的代码,他没说谢谢——而是找了领导
前端·javascript·ai编程
OpenTiny社区3 小时前
从零开发 AI 聊天页要两周?试试这款 Vue3 垂直对话组件库 TinyRobot,直接开箱即用
前端·vue.js·github
铁皮饭盒3 小时前
S3已成为文件存储标准,阿里/腾讯/华为云都支持,Bun率先原生支持
前端·javascript·后端
Cobyte3 小时前
22.Vue Vapor 组件 props 的实现
前端·javascript·vue.js
浮生望5 小时前
JS字符串与回文算法:从包装类到双指针的面试进阶之路
javascript·算法
疯狂的魔鬼5 小时前
一套 Schema 驱动四视图:记 useCrudSchemas 的设计与实践
前端·javascript·typescript
白雾茫茫丶5 小时前
探索 Nuxt.js 全栈能力:用 Better-Auth 打造类型安全的 RBAC 权限系统
前端·vue.js·nuxt.js
weedsfly5 小时前
栈和堆:JavaScript 内存的“旅馆”和“仓库”
前端·javascript·面试
向阳而生6605 小时前
文件上传也能玩出花?Vue3 教你优雅实现“选择文件”和“选择文件夹”🚀
vue.js