vue3-模版引用

发布时间:2024年01月21日

模版引用

ref 属性

场景:需要直接访问底层 DOM 元素。

方法:使用特殊的 ref 属性。

<input?ref="input">

ref 属性 允许我们在一个特定的 DOM 元素或子组件实例被挂载后,获得对它的直接引用。

访问模板引用

小 Demo: 当 input 组件挂载后 自动获取焦点

<script?lang="ts"?setup>
import?{?ref,?onMounted?}?from?'vue'

//?声明一个?ref?来存放该元素的引用
//?必须和模板里的?ref?同名
const?input?=?ref(null)

onMounted(()?=>?{
??input.value.focus()
})

watchEffect(()?=>?{
??if?(input.value)?{
????input.value.focus()
??}?else?{
????//?此时还未挂载,或此元素已经被卸载(例如通过?v-if?控制)
??}
})
</script>

<template>
??<div?class="container">
????<input?ref="input"?/>
??</div>
</template>

<style?lang="scss"?scoped>
.container?{
}
</style>

注意:只有组件挂载后才能访问模版引用。初次渲染时元素不存在所以在模版表达式上访问变量则为 null。

如果你需要侦听一个模板引用 ref 的变化,确保考虑到其值为 null 的情况

v-for 中的模板引用

<script?lang="ts"?setup>
import?{?ref,?onMounted?}?from?'vue'

const?list?=?ref([
??/*?...?*/
??1,?2,?3
])

const?itemRefs?=?ref([])

onMounted(()?=>?console.log(itemRefs.value))
</script>

<template>
??<div?class="container">
????<ul>
??????<li?v-for="item?in?list"?ref="itemRefs">
????????{{?item?}}
??????</li>
????</ul>
??</div>
</template>

<style?lang="scss"?scoped>
.container?{
}
</style>

效果:

应该注意的是,ref 数组并不保证与源数组相同的顺序。

函数模板引用

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

  2. 该函数会收到元素引用作为其第一个参数

<script?lang="ts"?setup>
import?{?ref,?onMounted?}?from?'vue'

const?input?=?ref([])

const?sum?=?(el)?=>?{
??console.log(el)
}
</script>

<template>
??<div?class="container">
????<button
??????:ref="
????????(el)?=>?{
??????????console.log(el)
????????}
??????"
????>
??????绑定内联函数
????</button>
????<br?/>
????<button?:ref="sum">绑定组件函数</button>
??</div>
</template>

<style?lang="scss"?scoped>
.container?{
}
</style>

效果:

  • 语法是 :ref 绑定函数。

  • 可以绑定内联函数。

  • 可以绑定组件函数。

  • 当元素被销毁时,函数也会被调用一次,此时引用参数为 null。

组件上的 ref

模板引用也可以被用在一个子组件上。这种情况下引用中获得的值是组件实例

<script?lang="ts"?setup>
import?{?onMounted,?ref?}?from?'vue'
import?ComA?from?'@/components/ComA.vue'

const?coma?=?ref<InstanceType<typeof?ComA>>()

onMounted(()?=>?{
??console.log(coma.value)
})
</script>

<template>
??<div?class="container">
????<ComA?ref="coma"></ComA>
??</div>
</template>

<style?lang="scss"?scoped>
.container?{
}
</style>

效果:

一个子组件使用的是选项式 API ,父组件对子组件的每一个属性和方法都有完全的访问权。

使用了 <script setup> 的组件是默认私有的,一个父组件无法访问到一个使用了 <script setup> 的子组件中的任何东西,除非子组件在其中通过 defineExpose 宏显式暴露

defineExpose 宏

<script?lang="ts"?setup>
import?{?ref?}?from?'vue'

const?a?=?ref(1)
const?b?=?ref(2)

//?像?defineExpose?这样的编译器宏不需要导入
defineExpose({
??a,
??b
})
</script>

<template>
??<div?class="container">我是子组件</div>
</template>

<style?lang="scss"?scoped>
.container?{
}
</style>

未定义效果:

定义效果:

文章来源:https://blog.csdn.net/wdk996/article/details/135723981
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。