小知识点

属性 ref

ref 被用来给元素或子组件注册引用信息

元素和组件上的refopen in new window支持传字符串和函数,若是使用选项式组件则通常用this.$refs.xxx来获取关联的元素。在组合式API setup 中,则推荐结合响应式API refopen in new window使用。

响应式 API 中普通用法

<template>
  <child-component ref="childRef">child</child-component>
</tempalte>

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

// 在 ts 中,需表明元素的类型
const childRef = ref<HTMLDivElement>();
</script>

响应式 API 中结合函数用法

<template>
  <!-- el 的类型是 Element |  ComponentPublicInstance -->
  <child-component :ref="el => childRef = el">child</child-component>
</tempalte>

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

const childRef = ref<Element | ComponentPublicInstance>();
</script>

通过函数获取节点信息且结合ts时,由于无法直接明确节点类型,因此节点可能是普通原生元素(p、div、button等)和vue组件,因此需要进行特别类型声明!

childRef的类型和我们最终需要使用的类型可能不是一致的,因此在使用的使用需要先根据所需进行类型断言,比如:

const childRef = ref<Element | ComponentPublicInstance>();
// 类型断言后,可以得到诸如 classList 和 className 等内容提示
const _childRef = childRef as HTMLDivElement;

v-for 结合 ref

v-forref函数结合时,会自动向响应式数组中填充内容。但需要注意,要确保每次更新之前重置ref

参考资料:refopen in new window模板引用open in new windowv-for 中的用法open in new window

watchEffect和它的兄弟们

假设遇到一个需求,我们需要在onUpdateonMounted中均要执行一段代码。此时一种做法是在这两个生命周期中都传入待执行代码。

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

const count = ref(0);
const fn = () => { console.log(count.value); }

onUpdated(fn);
onMounted(fn);
</script>

另一种做法是使用watchEffect函数,他会根据响应式状态自动应用和重新应用副作用,它会立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。

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

const count = ref(0)

watchEffect(() => console.log(count.value))
// -> logs 0

setTimeout(() => {
  count.value++
  // -> logs 1
}, 100)
</script>

但这有一个不算缺点的缺点,watchEffect的执行是在dom更新完毕之前,因此若有关于ref属性元素的操作会出现问题,解决方案

  1. watchEffect函数内做ref是否有无的预防性判断,没有则不执行内部代码;
  2. onMounted+watchEffect,在onMounted内再执行watchEffect,可以确保dom加载;
  3. watchEffect+flush:'post'参数:watchEffect可以为其传入第二个配置参数来明确函数执行的时机open in new windowpost表示在dom更新后才执行;

watchEffect+flush参数的使用方式在vue3.2+开始提供watchPostEffect函数来简化代替代码的书写,作用都是一样的!

参考资料:watchEffectopen in new window副作用刷新时机open in new window

插槽

插槽在没有任何具名插槽的情况下,可以不明确写出 default 插槽名:

<template v-slot:default></template>

而在含有其他具名插槽的情况时,则需要明确写明使用,否则会无法正确渲染内容:

<template v-slot:header></template>
<template v-slot:default></template>
<template v-slot:footer></template>
最近更新:
Contributors: untilthecore