Skip to content

宏函数

defineExpose()

<script setup> 内声明的数据或函数默认是私有的,当父组件通过 ref 获取到子组件的引用后,无法通过 ref 直接访问子组件中声明的数据或函数。

此时,我们可以通过 defineExpose 编译器宏来显式指定在 <script setup> 组件中要暴露出去的属性:

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

const a = 1
const b = ref(0)

const increment = (step = 1) => {
  b.value += step
}

defineExpose({
  a,
  b,
  increment
})
</script>

当父组件通过 ref 获取到子组件的引用之后,可以通过 子组件引用.value 访问到暴露的数据或函数:

vue
<script setup>
import MyCom from './components/05.自定义插件/03.defineExpose.vue'
import { ref, onMounted, watch } from 'vue'

// 1. 声明引用对象
const myComRef = ref(null)

// 3. 在 js 中,需要在父组件挂载完成后,才能访问到子组件的 ref 引用
onMounted(() => {
  // 获取子组件通过 defineExpose 暴露的数据
  console.log(myComRef.value)

  // 侦听子组件中的响应式数据的变化
  // 必须在 onMounted 中使用 watch 侦听子组件
  // 否则,子组件还没有创建完毕,无法获取数据
  watch(
    () => myComRef.value.b,
    (newValue, oldValue) => {
      console.log(newValue, oldValue)
    }
  )
})
</script>

<template>
  <div>
    <div class="app-title">App.vue</div>
    <!-- 4. 在模板区域,直接 ref 会自动解包,不需要使用 .value 属性 -->
    <button @click="myComRef.b++">b++</button>
    <hr />

    <!-- 2. 建立引用关系 -->
    <MyCom ref="myComRef" />
  </div>
</template>

<style scoped>
.app-title {
  font-size: 30px;
}
</style>

响应式 API 的工具函数

toRefs()

reactive 创建的响应式数据使用解构赋值的操作时,会导致解构出来的数据丢失响应性的问题。我们可以使用 toRefs() 这个 API 对 reactive 数据进行包裹,这样解构出来的数据依然具有响应性。

vue
<template>
  <p>{{ info }}</p>
  <p>年龄:{{ age }}</p>
  <button @click="age++">age++</button>
</template>

<script setup>
import { reactive, toRefs } from 'vue'

const info = reactive({
  name: 'zs',
  age: 18
})

// 这里的解构会丢失响应性
// const { age } = info

// age 具有响应性
const { age } = toRefs(info)
console.log(age)
</script>

天不生夫子,万古长如夜