Vue3中的ref模板引用的使用

时间:2021-03-01 01:28:07

ref用于对元素的标记,通过ref可以获取到对应元素上的属性和方法。

一、访问模板引用

在Vue3中为了通过组合式 API 获得该模板引用,我们需要声明一个同名的 ref。

<template>
  <div>
    <div ref="element">{{ item }}</div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
const element=ref(null)
console.log(element);
const item = ref("我是一个元素");
</script>

<style>
</style>

注意,你只可以在组件挂载后才能访问模板引用。如果你想在模板中的表达式*问 input,在初次渲染时会是 null。这是因为在初次渲染前这个元素还不存在呢!

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

<template>
  <div>
    <div ref="element">{{ item }}</div>
  </div>
</template>

<script setup>
import { ref , watchEffect} from 'vue';
const element=ref(null)
const item = ref("我是一个元素");
watchEffect(()=>{
  if(element.value){
    console.log(element);
  }else{
    console.log('未加载');
  }
})
</script>

<style>
</style>

二、v-for中的模板引用

当在 v-for 中使用模板引用时,对应的 ref 中包含的值是一个数组,它将在元素被挂载后包含对应整个列表的所有元素,需要注意的是,ref 数组并不保证与源数组相同的顺序。

<template>
  <div>
    
    <div v-for="(item,index) in 10" :key="index" ref="element">{{ item }}</div>
  </div>
</template>

<script setup>
import { ref , watchEffect} from 'vue';
const element=ref([])
const item = ref("我是一个元素");
watchEffect(()=>{
  if(element.value){
    console.log(element);
  }else{
    console.log('未加载');
  }
})
</script>

<style>
</style>

三、组件上的ref

如果一个子组件使用的是选项式 API 或没有使用 <script setup>,被引用的组件实例和该子组件的 this 完全一致,这意味着父组件对子组件的每一个属性和方法都有完全的访问权。这使得在父组件和子组件之间创建紧密耦合的实现细节变得很容易,当然也因此,应该只在绝对需要时才使用组件引用。大多数情况下,你应该首先使用标准的 props 和 emit 接口来实现父子组件交互。

子组件:

<template>
  <div>
    {{ data }}
  </div>
</template>

<script>
export default {
data(){
  return{
    data:'我是子元素'
  }
}
}
</script>

<style>

</style>

父组件:

<template>
  <div>
    <Child ref="child"></Child>
  </div>
</template>

<script setup>
import Child from "@/components/child.vue"
import { ref, watch ,watchEffect} from "vue"
const child=ref(null)
watchEffect(()=>{
  if(child.value){
    console.log(child.value.data);
  }
})

</script>

<style>

</style>

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

子组件:

<template>
  <div>
    {{ data }}
  </div>
</template>

<script setup>
import { ref } from "vue";

const data = ref('我是子元素')
defineExpose({
  data
})
</script>

<style>

</style>

父组件:

<template>
  <div>
    <Child ref="child"></Child>
  </div>
</template>

<script setup>
import Child from "@/components/child.vue"
import { ref, watch ,watchEffect} from "vue"
const child=ref(null)
watchEffect(()=>{
  if(child.value){
    console.log(child.value.data);
  }
})

</script>

<style>

</style>

相关文章