vue3_defineExpose的用法

官网说明

  • defineExpose用于子组件向其父组件传值.

常规示例

子组件: /components/testCom1.vue

<template>
  <div id="a_container"></div>
</template>

<script setup>
import { ref, reactive, defineExpose } from 'vue'
const a = ref(Math.round(Math.random() * 100))
const b = reactive({
  num: Math.round(Math.random() * 100),
})
const c = 77
defineExpose({ a, b, c })
</script>

<style scoped lang="scss"></style>
  • 在子组件中声明了一个a变量保存随机生成数据, 通过

父组件: App.vue

<template>
  <div id="app">
    <test-com1 ref="testCom1Ref"></test-com1>
  </div>
</template>

<script setup>
import testCom1 from './components/testCom1.vue'
import { ref, onMounted } from 'vue'
const testCom1Ref = ref(null)
onMounted(() => {
  console.log(testCom1Ref.value)
  const { a, b, c } = testCom1Ref.value
  console.log(a) // 随机数
  console.log(b) // {num : 随机数}
  console.log(c) // 77
})
</script>

<style></style>

监听defineExpose返回的数据的变化实现子组件向父组件传递数据

  • 如下: 子组件抛出数据, 并在指定时间后更新数据; 父组件在onMounted中通过watch监听数据, 只能监听到reactive定义的数据的变化; 因此可以通过defineExpose来返回子组件中的reactive定义的proxy对象, 然后在父组件中通过watch来监听该数据的变化, 实现子组件向父组件传递数据
// components/testCom1.vue
<template>
  <div id="a_container"></div>
</template>

<script setup>
import { ref, reactive, defineExpose } from 'vue'
const a = ref(10) // 获取一个随机数
const b = reactive({ 
  num: 20 // 获取一个随机数
})
let c = 30 

setTimeout(() => {
  a.value = 100
  b.num = 200
  c = 300
}, 2000)
defineExpose({ a, b, c })
</script>

<style scoped lang="scss"></style>
// App.vue
<template>
  <div id="app">
    <test-com1 ref="testCom1Ref"></test-com1>
  </div>
</template>

<script setup>
import testCom1 from './components/testCom1.vue'
import { ref, onMounted, watch, onBeforeMount } from 'vue'
const testCom1Ref = ref(null)
onMounted(() => {
  const { a, b, c, d } = testCom1Ref.value
  console.log(typeof a) // number
  console.log(typeof b) // object
  console.log(typeof c) // number
  console.log(typeof d) // object
  console.log(a) // 10
  console.log(b.num) // 20
  console.log(c) // 30
  console.log(d.num) // 40

  watch(b, () => {
    console.log('b更新')
    console.log(b) //{num:200}
  })
  watch(
    () => d,
    () => {
      // 不执行, 因为watch只对监听proxy对象有反应
      console.log('d更新')
      console.log(d)
    }
  )
  setTimeout(() => {
    console.log(a) // 10
    console.log(b.num) // 200
    console.log(c) //30
    console.log(d.num) // 400
  }, 3000)
})
</script>

<style></style>

父组件中修改子组件defineExpose抛出的数据, 实现父组件向子组件回传数据

  • 子组件中通过reactive定义的数据, 通过defineExpose抛出后可以在父组件中获取得到;
  • 父组件中修改defineExpose抛出的, 在子组件中通过reactive定义的数据, 可以触发子组件的数据响应
// components/testCom1.vue
<template>
  <div id="a_container">
    <p key="hasdhj">{{ a }}</p>
    <!-- b由20变化为200, 变化为2000 -->
    <p key="asasda">{{ b.num }}</p>
    <p key="zxcwwd">{{ c }}</p>
    <p key="xcqweq">{{ d.num }}</p>
  </div>
</template>

<script setup>
import { ref, reactive, defineExpose } from 'vue'
const a = ref(10) // 获取一个随机数
const b = reactive({
  num: 20 // 获取一个随机数
})
let c = 30
const d = { num: 40 }

setTimeout(() => {
  a.value = 100
  b.num = 200
  c = 300 // 因为a,b响应式数据被更新, 所以c也会因为页面更新而更新, 但它本身不具有响应式
  d.num = 400 // 因为a,b响应式数据被更新, 所以d也会因为页面更新而更新, 但它本身不具有响应式
}, 2000)
defineExpose({ a, b, c, d })
</script>

<style scoped lang="scss"></style>
// App.vue
<template>
  <div id="app">
    <test-com1 ref="testCom1Ref"></test-com1>
  </div>
</template>

<script setup>
import testCom1 from './components/testCom1.vue'
import { ref, onMounted, watch, onBeforeMount } from 'vue'
const testCom1Ref = ref(null)
onMounted(() => {
  const { a, b, c, d } = testCom1Ref.value
  console.log(typeof a) // number
  console.log(typeof b) // object
  console.log(typeof c) // number
  console.log(typeof d) // object
  console.log(a) // 10
  console.log(b.num) // 20
  console.log(c) // 30
  console.log(d.num) // 40

  watch(b, () => {
    // 每次更新都会执行
    console.log('b更新')
    console.log(b) 
  })
  watch(
    () => d,
    () => {
      // 不执行, 因为watch只对监听proxy对象有反应
      console.log('d更新')
      console.log(d)
    }
  )
  setTimeout(() => {
    console.log(a) // 10
    console.log(b.num) // 200
    console.log(c) //30
  }, 3000)

  // setTimeout(() => {
  //   b.num = 2000
  //   d.num = 4000 // 不具有响应式, 但因为响应式数据b变化, 页面重新渲染, d数据也会被重新渲染, 造成该数据有响应式的假象
  // }, 5000);

  setTimeout(() => {
    b.num = 2000
  }, 5000)
  setTimeout(() => {
    d.num = 4000 // 不具有响应式, 且子组件数据变化但页面并不更新
  }, 5000)
})
</script>

<style></style>
posted @ 2024-03-29 00:20  Syinho  阅读(374)  评论(0编辑  收藏  举报