Vue3 学习总结补充(二)

400 阅读1分钟

image.png

Vue3新增的组件通讯API:defineProps() defineEmits()defineExpose()

defineProps() defineEmits()defineExpose() 只能在 <script setup> 中使用(的编译器宏),使用前不需要 通过 import 方式 导入,它们会随着 <script setup> 的处理过程一同被编译掉。

1、defineProps()

使用场景: 父组件传值给子组件(父传子)

说明: defineProps() 接收与 props 选项相同的值,声明的 props 会自动暴露给template模板(在子组件template中可以直接使用defineProps 传过来的父组件的值 )。

使用方法如下:

父组件:App.vue

<template>
  <div class="app">app组件(父组件)</div>
  <!-- 子组件 -->
  <Child :countData="count" :infData="info" />
</template>

<script setup>
import { ref, reactive } from 'vue'
import Child from './components/Child.vue'

const count = ref(10)
const info = reactive({
  name: 'xiaozhu',
  age: 18,
})

</script>
<style scope>
.app {
  border: 1px solid black;
  padding: 50px;
}
</style>

子组件:Child.vue

<template>
  <div class="child">
    Child组件
    <div>父组件传过来的数据count:{{ countData }} info:{{ infData.name }}-{{ infData.age }}</div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
// defineProps 不需要 通过 import 导入,直接可以使用,声明的 props 会自动暴露给 template模板
const childData = defineProps({
  countData: {
    type: Number,
    default: 0,
  },
  infData: Object,
})

// 想要在子组件的setup中 获取父组件传过来的数据,需要 接受 defineProps 返回值,通过返回值获取对应数据
console.log('childData.countData', childData.countData)
</script>
<style scope>
.child {
  border: 1px solid red;
  padding: 50px;
}
</style>

父传子数据流程:

效果展示:

2、defineEmits()

使用场景: 子组件传值给父组件(子传父)

说明: defineEmits() 接收与 emits 选项相同的值,子组件通过 defineEmits() 声明的 emit函数传递方法和对应的数据,父组件根据子组件传过来的方法进行自定义事件,然后绑定父组件中定义的方法进行接收。

使用方法如下:

父组件:App.vue

<template>
  <div class="app">app组件(父组件) {{ count }} {{ info.name }}-{{ info.age }}</div>

  <!-- 子组件 -->
  <Child @changeCount="change" @modifyInfo="modify" />
</template>

<script setup>
import { ref, reactive } from 'vue'
import Child from './components/Child.vue'

const count = ref(10)

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

// 改变 count值
const change = (num1, num2) => {
  // num1 和 num2 是从 子组件传过来的 数据,10 和 20
  console.log('num1', num1, 'num2', num2)
  count.value += num1 + num2
}

const modify = (data) => {
  // data 是从子组件传过来的 数据 { name: '筱竹', age: 20 }
  console.log('data', data)
  const { name, age } = data
  info.name = name
  info.age = age
}
</script>

<style scope>
.app {
  border: 1px solid black;
  padding: 50px;
}
</style>

子组件:Child.vue

<template>
  <div class="child">
    Child组件
    <button @click="handle()">处理</button>
  </div>
</template>

<script setup>
const emit = defineEmits(['changeCount', 'modifyInfo'])
const handle = () => {
  // 子组件通过 emit 向父组件传递数据
  console.log('Child组件中的 emit事件 触发了')
  emit('changeCount', 10, 20)
  emit('modifyInfo', { name: '筱竹', age: 20 })
}
</script>
<style scope>
.child {
  border: 1px solid red;
  padding: 50px;
}
</style>

父传子数据流程:

效果展示:

3、defineExpose()

使用场景: 子组件向外暴露属性和方法给父组件

说明: 使用了 的子组件中的任何属性和方法,如果子组件想要向外暴露组件中的属性和方法,需要使用defineExpose() 来显式指定在 <script setup> 组件中要暴露出去的属性和方法。

使用方法如下:

父组件:App.vue

<template>
  <div class="app">
    app组件(父组件)
    {{ info }} - {{ data.bookName }}- {{ data.author }}
    <br />
    <button @click="getData">获取子组件中的数据</button>
  </div>
  <!-- 子组件 -->
  <Child ref="getMsg" />
</template>

<script setup>
import { ref, toRefs } from 'vue'
import Child from './components/Child.vue'
// 在父组件中需要设置 ref 获取到 子组件中的数据
const getMsg = ref(null)

const info = ref(null)
const data = ref({})

const getData = () => {
  // 在子组件中 通过 defineExpose 编译器宏 显式暴露数据后,可以在父组件中 通过 ref 就获取到子组件中数据了,并可以对子组件中的数据进行操作。
  console.log('getMsg.value.msg', getMsg.value.msg)
  console.log('getMsg.value.msg', getMsg.value.infoData)
  getMsg.value.release()
  const { msg, infoData } = getMsg.value
  info.value = msg
  data.value = infoData
}
</script>

<style scope>
.app {
  border: 1px solid black;
  padding: 50px;
}
</style>

子组件:Child.vue

import { reactive } from 'vue';
<template>
  <div class="app">
    Child组件
    {{ msg }}-{{ infoData.bookName }}-{{ infoData.author }}
  </div>
</template>

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

const msg = ref('hello vue3')
const infoData = reactive({
  bookName: '《Vue3.js项目实战开发》',
  author: '筱竹',
})
const release = () => {
  console.log('我是子组件中的release方法')
}
// 使用了 <script setup> 的组件是默认私有的:一个父组件无法访问到一个使用了 <script setup> 的子组件中的任何东西,除非子组件在其中通过 defineExpose 宏显式暴露,defineExpose 这样的编译器宏不需要导入就可以直接使用。
defineExpose({
  msg,
  infoData,
  release,
})
</script>
<style scope>
.child {
  border: 1px solid red;
}
</style>

子组件数据暴露流程:

效果展示: