【Vue3】11-父子组件传参

67 阅读1分钟

1. 父传子 - defineProps

1.1 js 中的写法

// App.vue
<template>
    <!-- 给 子组件 绑定响应式的值 -->
    <Child :title="title"></Child>
</template>

<script setup>
    import { ref } from "vue" 
    import { Child } from "..."
    let title = ref<string>("标题")
</script>

// Child.vue
<template>
    <!-- 在 子组件 模板中直接使用 -->
    <div>{{ title }}</div>
</template>

<script setup>
    // 调用 defineProps 后,接收父组件传进来的属性
    // title 可以直接在模板中使用,如果要在 js 中使用,则需要一个变量来接收返回值
    const props = defineProps({
        title: {
            type: String,
            default: "默认值"
        }
    })
    
    console.log(props.title)  // 在 js 中访问 title
</script>

1.2 ts 中的写法

// App.vue
<template>
    <Child :title="title" :arr="[1,2,3]"></Child>
</template>
<script setup lang="ts">
    import { ref } from "vue"
    import Child from "..."
    
    let title = ref<string>("标题")
</script>

// Child.vue
<template>
    {{ title }}
    {{ arr }}
</template>
<script setup lang="ts">
const props = withDefaults(defineProps<{
    title: String,
    arr: number[]
}>(), {
    // 下面这样写是不行的
    // title: "默认值",
    // arr: [4,5,6]
    
    // 值应该作函数返回值,防止引用
    title: () => "默认值",
    arr: () => [4,5,6]
})

console.log(props.title, props.arr)  // 标题 [1,2,3]
</script>

2. 子传父 - defineEmits

2.1 js 中的写法

// App.vue
<template>
    <Child @on-click="receive"></Child>
</template>
<script setup>
    import Child from "..."
    const receive = (...args) => {
        console.log("我是父组件,收到了")
        console.log(...args)  // value1 value2
    }
</script>

// Child.vue
<template>
    <button @click="send"></button>
</template>
<script setup>
    // 调用 defineEmits 收集父组件自定义的事件
    const emit = defineEmits(['on-click'])
    
    const send = () => {
        // 触发父组件自定义的事件,并传参
        emit("on-click", "value1", "value2")
    }
</script>

2.2 ts 中的写法

// App.vue
<template>
    <Child @on-click="receive"></Child>
</template>

<script setup lang="ts">
import Child from './components/Child.vue'  

function receive(){
    console.log("我是父组件,收到了")
    console.log(...arguments)
}
</script>


// Child.vue
<template>
    <button @click="send">给父组件传值</button>
</template>

<script setup lang="ts">
const emit = defineEmits<{
    (e:"on-click", param1: string, param2: string):void
}>()
const send = () => {
    let param1 = "value1"
    let param2 = "value2"
    // 触发自定义事件,并传参
    emit("on-click", param1, param2)
}
</script>

3. 子组件给父组件暴露属性和方法 - defineExpose

// App.vue
<template>
    <Child ref="childRef"></Child>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import Child from './components/Child.vue'  

// const childRef = ref()
// const childRef = ref<InstanceType<typeof Child>>()
// onMounted(() => {
//     console.log(childRef.value.name, childRef.value.open)
// })

// ↑ 或者 ↓

const childRef = ref<InstanceType<typeof Child>>()  // 类型限定
onMounted(() => {
    console.log(childRef.value?.name, childRef.value?.open)
})
</script>

// Child.vue
<script setup lang="ts">
// defineExpose 给父组件暴露一些属性和方法
defineExpose({
    name: 'lzy',
    open: () => console.log(111)
})
</script>