Vue3系列(七)Composition Api之父子组件传参及调用

774 阅读1分钟

父组件给子组件传值

父组件通过 v-bind给子组件绑定一个数据

// parent.vue
<template>
  <div>
    <children :params="params"></children>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue' 
import children from './children'

const params = ref<string>('我是传递过来的数据')
</script>

子组件通过defineProps接收父组件传递过来的数据 defineProps 是vue3的写法并且是一个仅 <script setup> 中可用的编译宏命令,并不需要显式地导入;在vue3的非语法糖setup和在vue2中的写法是 props 。

注意: 因为所有的 props 都遵循着单向数据流原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。所以子组件无法直接修改父组件传递过来的值

// children.vue
<template>
  <div>
    {{ params }}
  </div>
</template>

<script setup lang="ts">
const props = defineProps({
  params: String,
  title: {
    type: String,
    default: '我是默认值'
  }
})

// 如果使用ts,可以通过泛型标注来声明 props
const props = defineProps<{
  params?: string  // 非必传
}>()

// 如果使用ts且需要设置默认值 可以通过withDefaults
const props = withDefaults(defineProps<{
    params?: string,
    arr: string[],
}>(), {
    // 默认值
    arr: () => ['默认值1', '默认值2']
})
</script>

子组件给父组件传值

通过defineEmits派发一个事件,通过事件传递参数

defineEmits 是vue3的写法并且是一个仅 <script setup> 中可用的编译宏命令,并不需要显式地导入;在vue3的非语法糖setup中的写法是 emits 。

// children.vue
<template>
  <div>
    <button @click="handleSendParams">派发事件给父组件</button>
  </div>
</template>

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

const emit = defineEmits(['onSendParams'])

const handleSendParams = () => {
    emit('onSendParams', '传递给父组件的数据')
}

// 如果使用ts,可以通过泛型标注来声明 emit
const emit = defineEmits<{
  (e: 'onSendParams', params: string): void
}>
</script>

父组件通过v-on监听子组件派发的事件

// parent.vue
<template>
  <div>
    <children @onSendParams="handleGetParams"></children>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue' 
import children from './children'

const handleGetParams = (params) => {
    console.log(params) // 传递给父组件的数据

}
</script>

子组件向父组件暴露属性或方法

使用 <script setup> 的组件是默认关闭的——即通过模板引用或者 $parent 链获取到的组件的公开实例,不会暴露任何在 <script setup> 中声明的绑定。即我们无法通过ref获取到组件的任何属性或方法

可以通过 defineExpose 来显式指定在 <script setup> 组件中要暴露出去的属性:

// children.vue

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

const list = reactive<number[]>(['1', '2', '3'])

const handle = () => {
  console.log('handle')
}

defineExpose({
  list,
  handle
})
</script>

父组件通过ref获取子组件暴露出来的属性

// parent.vue
<template>
  <div>
    <children ref=""childrenRef></children>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue' 
import children from './children'

// 声明一个同名的ref,获得组件的引用
const childrenRef = ref()

console.log(childrenRef.value) // { list: ['1', '2', '3'] }

childrenRef.handle() // 调用子组件的方法
</script>