面试题:Vue 中怎么获取 DOM 节点?

在 Vue 中,获取 DOM 节点是通过 ref 特性来实现的。直接操作 DOM 不是 Vue 推荐的首选方式(Vue 提倡声明式渲染和数据驱动),但在某些特定场景下(如触发焦点、测量元素尺寸、集成第三方库等)仍然需要访问原生 DOM 元素。

核心方法:使用 ref

  1. 在模板中定义 ref
    在你想要获取的 HTML 元素上添加 ref 属性,并为其指定一个唯一的名称。
  2. 在组件实例中通过 $refs 访问
    在组件的 mounted 或其他生命周期钩子及方法中,通过 this.$refs.名称 来访问对应的 DOM 节点。

详细示例

基本用法

<template>
  <div>
    <!-- 为 input 元素绑定 ref -->
    <input ref="myInput" type="text" placeholder="Hello Vue!" />
    <button @click="focusInput">聚焦输入框</button>
  </div>
</template>

<script>
export default {
  methods: {
    focusInput() {
      // 通过 $refs 获取 DOM 元素并调用其 focus 方法
      this.$refs.myInput.focus();
    }
  },
  mounted() {
    // DOM 已经渲染完成,可以安全地访问 $refs
    console.log(this.$refs.myInput); // 输出: <input> 元素
  }
}
</script>

重要注意事项

  1. 时机问题
    • this.$refs 只在组件挂载后 (mounted) 才可用。
    • created 钩子中,DOM 尚未生成,this.$refs 会是 undefined
    • 如果元素是通过 v-if 动态渲染的,那么只有当 v-iftrue 时,$refs 才存在。
  2. ref 的值取决于绑定的目标
    • 绑定到原生 HTML 元素上:$refs.xxx原生的 DOM 元素
    • 绑定到子组件上:$refs.xxx子组件的 Vue 实例,而不是它的根 DOM 元素。
  3. v-for 中的 ref
    • ref 用在 v-for 内部时,$refs.xxx 将是一个包含所有对应 DOM 节点或组件实例的数组
    <li v-for="item in list" :key="item.id" ref="listItems">{{ item.name }}</li>
    // this.$refs.listItems 是一个包含所有 <li> 元素的数组
  4. $refs 不是响应式的
    • this.$refs 对象本身不会触发视图更新。它只是一个方便访问的属性集合。
  5. Vue 3 Composition API (setup)
    • <script setup> 中,需要使用 ref() 函数创建一个响应式引用。
    <script setup>
    import { ref, onMounted } from 'vue'
    
    // 创建一个 ref 引用
    const myInput = ref(null)
    
    function focusInput() {
      // 通过 .value 访问 DOM 元素
      myInput.value.focus()
    }
    
    onMounted(() => {
      console.log(myInput.value) // DOM 元素
    })
    </script>
    
    <template>
      <input ref="myInput" type="text" />
      <button @click="focusInput">聚焦</button>
    </template>

替代方案(更 Vue 化的方式)

虽然 ref 是获取 DOM 的标准方法,但应优先考虑以下更符合 Vue 理念的方式:

  • 使用 v-model:对于表单元素,尽量使用 v-model 进行双向绑定,而不是手动操作 value
  • 通过 propsevents 通信:避免直接访问子组件的 DOM,而是通过传递数据和触发事件来交互。
  • 计算属性和侦听器:用数据变化驱动视图,而不是直接修改 DOM。

总结

在 Vue 中,获取 DOM 节点的唯一标准方法是使用 ref 特性。步骤如下:

  1. 在目标元素上添加 ref="name"
  2. mounted 钩子或之后的方法中,通过 this.$refs.name 访问该 DOM 节点。

记住:ref 应作为最后的手段,在无法通过数据驱动解决时才使用。在 Vue 3 的组合式 API 中,则使用 ref() 函数配合 .value 来访问。

THE END
喜欢就支持一下吧
点赞11 分享