现在位置: 首页 > Vue3 教程 > 正文

Vue3 ref 属性

Vue3 内置属性 Vue3 内置属性


ref 属性用于给元素或子组件注册引用信息,以便在 JavaScript 代码中直接访问 DOM 元素或组件实例。


基本说明

ref 是 Vue 中获取 DOM 元素或组件实例的重要方式。它允许我们在 Vue 实例挂载后直接操作 DOM 或调用子组件的方法。

  • 类型: String | Function
  • 作用: 访问 DOM 元素或子组件实例,进行焦点控制、方法调用等操作。

基本用法

1、Options API 中使用 ref

在 Options API 中,ref 注册的引用会存储在组件实例的 $refs 对象中:

实例

<template>
  <div>
    <input type="text" ref="inputField" />
    <button @click="focusInput">聚焦输入框</button>
  </div>
</template>

<script>
export default {
  methods: {
    focusInput() {
      // 通过 $refs 访问 DOM 元素
      this.$refs.inputField.focus()
    }
  }
}
</script>

2、Composition API 中使用 ref

在 Composition API 中,推荐使用 useTemplateRef 来获取模板引用:

实例

<template>
  <div>
    <input type="text" ref="inputField" />
    <button @click="focusInput">聚焦输入框</button>
  </div>
</template>

<script setup>
import { useTemplateRef } from 'vue'

// 创建与模板中 ref 名匹配的引用
const inputField = useTemplateRef('inputField')

function focusInput() {
  // 直接访问 DOM 元素
  inputField.value?.focus()
}
</script>

使用场景

1、访问 DOM 元素

使用 ref 可以直接访问 DOM 元素,进行焦点控制、获取值等操作:

实例

<template>
  <div>
    <input type="text" ref="username" placeholder="用户名" />
    <button @click="getValue">获取值</button>
  </div>
</template>

<script>
export default {
  methods: {
    getValue() {
      // 获取输入框的值
      const value = this.$refs.username.value
      console.log('输入的值:', value)
    }
  }
}
</script>

2、访问子组件实例

使用 ref 可以访问子组件的实例,调用子组件的方法或访问其数据:

实例

<!-- 父组件 -->
<template>
  <div>
    <child-component ref="childRef"></child-component>
    <button @click="callChildMethod">调用子组件方法</button>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: {
    ChildComponent
  },
  methods: {
    callChildMethod() {
      // 调用子组件的方法
      this.$refs.childRef.sayHello()
      // 访问子组件的数据
      console.log('子组件数据:', this.$refs.childRef.message)
    }
  }
}
</script>

3、函数式 ref

ref 也可以接受一个函数,这个函数会在每次更新时被调用,可以完全控制引用的存储位置:

实例

<template>
  <div>
    <input type="text" :ref="el => inputEl = el" />
    <button @click="focusInput">聚焦</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      inputEl: null
    }
  },
  methods: {
    focusInput() {
      this.inputEl?.focus()
    }
  }
}
</script>

注意事项

ref 注册时机:因为 ref 本身是由渲染函数的结果创建的,所以必须在组件挂载后才能访问它们。如果在 created 生命周期钩子中访问,$refs 还是空对象。

非响应式$refs 是非响应式的,因此不应该在模板中将其用于数据绑定。只在 JavaScript 中使用它进行 DOM 操作。

避免滥用 ref:尽可能通过数据驱动和事件处理来操作 DOM 和子组件。过度使用 ref 会使代码难以维护。

实例

<!-- 不推荐:在 created 中访问 ref -->
<script>
export default {
  created() {
    console.log(this.$refs.inputField) // undefined
  },
  mounted() {
    console.log(this.$refs.inputField) // 可以访问
  }
}
</script>

与 v-for 配合

ref 也可以用于 v-for,会创建一个包含所有对应 DOM 元素或组件实例的数组:

实例

<template>
  <div>
    <div v-for="(item, index) in items" :key="item.id" :ref="el => setItemRef(el, index)">
      {{ item.name }}
    </div>
    <button @click="logRefs">打印所有引用</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, name: '项目一' },
        { id: 2, name: '项目二' },
        { id: 3, name: '项目三' }
      ],
      itemRefs: []
    }
  },
  methods: {
    setItemRef(el, index) {
      if (el) {
        this.itemRefs[index] = el
      }
    },
    logRefs() {
      console.log('所有引用:', this.itemRefs)
    }
  }
}
</script>

Vue3 内置属性 Vue3 内置属性