Skip to content

模板引用

用于直接访问DOM元素或子组件实例,常用于集成第三方DOM库,手动聚焦输入框、测量元素尺寸等场景。

基础用法

在模板中用ref属性记录目标,在逻辑层用同名ref变量接收。

vue
<template>
	<!-- 绑定DOM元素 -->
	<input ref="inputRef" />
	<!-- 绑定组件 -->
	<child-comp ref="childRef" />

    <ul>
        <!-- 绑定循环生成的元素 -->
        <li v-for="item in list" ref="itemRefs">
        	{{ item }}
        </li>
    </ul>
</template>
<script setup>
    ...
    // 接收DOM元素
    const inputRef = ref<HTMLInputElement | null>(null)
    // 接收组件实例
    const childRef = ref<HTMLInputElement | null>(null)
    // 声明为数组
    const itemsRefs = ref<(HTMLInputElement | null)[]>([])
    
    onMounted(() =>{
        // 访问DOM元素
        inputRef.value.focus()
        // 访问组件方法(需组件暴露)
        childRef.value?.childMethod()
        // ref 数组并不保证与源数组相同的顺序
        itemRefs.value
    })
</script>

辅助函数 useTemplateRef

Vue3.5+,返回一个浅层 ref,其值将与模板中的具有匹配 ref attribute 的元素或组件同步。

javascript
<template>
	<!-- 绑定DOM元素 -->
	<input ref="inputRef" />
	<!-- 绑定组件 -->
	<child-comp ref="childRef" />
        
    <ul>
        <!-- 绑定循环生成的元素 -->
        <li v-for="item in list" ref="itemRefs">
        	{{ item }}
        </li>
    </ul>
</template>

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

// 第一个参数必须与模板中的 ref 值匹配
const inputRef = useTemplateRef<HTMLInputElement>('inputRef')
const childRef = useTemplateRef<InstanceType<typeof ChildCcmp>>('childRef')
const itemRefs = useTemplateRef<HTMLInputElement[]>('items')

onMounted(() => {
  input.value.focus()
  childRef.value?.childMethod()
})
</script>

函数模板引用

除了使用字符串值作名字,ref attribute 还可以绑定为一个函数,会在每次组件更新时都被调用。

vue
<!-- 当绑定的元素被卸载时,函数也会被调用一次,此时的 el 参数会是 null -->
<input :ref="(el) => { /* 将 el 赋值给一个数据属性或 ref 变量 */ }">

组件暴露内容

使用了 <script setup> 的组件是默认私有的:一个父组件无法访问到一个使用了 <script setup> 的子组件中的任何东西,除非子组件在其中通过 defineExpose 宏显式暴露(defineExpose必须在任何 await 操作之前调用。否则,在 await 操作后暴露的属性和方法将无法访问。):

javascript
<script setup>
import { ref } from 'vue'

const a = 1
const b = ref(2)

// 像 defineExpose 这样的编译器宏不需要导入
defineExpose({
  a,
  // ref 会自动解包
  b
})
</script>

Released under the MIT License.