Vue3系列7–父子组件传参()

1 父组件传递给子组件

父组件通过v-bind绑定一个数据,然后子组件通过defineProps接受传过来的值。

<template>
    <div class="layout">
        <Menu v-bind:data="data"  title="我是标题"></Menu> // 传递字符串的时候可以不需要v-bind,传递非字符串类型需要加v-bind
        <div class="layout-right">
            <Header></Header>
            <Content></Content>
        </div>
    </div>
</template>
 
<script setup lang="ts">
import Menu from './Menu/index.vue'
import Header from './Header/index.vue'
import Content from './Content/index.vue'
import { reactive } from 'vue';
 
const data = reactive<number[]>([1, 2, 3])
</script>

子组件接受值,通过defineProps 来接受 defineProps是无须引入的直接使用即可

<template>
    <div class="menu">
        菜单区域 {{ title }}
        <div>{{ data }}</div>
    </div>
</template>
 
<script setup lang="ts">
defineProps<{
    title:string,
    data:number[]
}>()
</script>

TS特有的默认值方式

withDefaults是个函数也是无须引入开箱即用接受一个props函数第二个参数是一个对象设置默认值

type Props = {
    title?: string,
    data?: number[]
}
withDefaults(defineProps<Props>(), {
    title: "张三",
    data: () => [1, 2, 3]
})

2 子组件给父组件传参

是通过defineEmits派发一个事件。

<template>
    <div class="menu">
        <button @click="clickTap">派发给父组件</button>
    </div>
</template>
 
<script setup lang="ts">
import { reactive } from 'vue'
const list = reactive<number[]>([4, 5, 6])

const emit = defineEmits(['on-click'])
const clickTap = () => {
    emit('on-click', list)
}
</script>

我们在子组件绑定了一个click 事件 然后通过defineEmits 注册了一个自定义事件,点击click 触发 emit 去调用我们注册的事件 然后传递参数,父组件接受子组件的事件。

<template>
    <div class="layout">
        <Menu @on-click="getList"></Menu>
        <div class="layout-right">
            <Header></Header>
            <Content></Content>
        </div>
    </div>
</template>
 
<script setup lang="ts">
import Menu from './Menu/index.vue'
import Header from './Header/index.vue'
import Content from './Content/index.vue'
import { reactive } from 'vue';
 
const data = reactive<number[]>([1, 2, 3])
const getList = (list: number[]) => {
    console.log(list,'父组件接受子组件');
}
</script>

我们从Menu 组件接受子组件派发的事件on-click 后面是我们自己定义的函数名称getList,会把参数返回过来。

3 子组件暴露给父组件内部属性

在 中,默认不会暴露任何在 中声明的绑定,即不能通过模板 获取到组件实例声明的绑定。 提供了 编译器宏,可以显式地暴露需要暴露的组件中声明的变量和方法。

Vue3 
<script setup> 
ref
Vue3
defineExpose
// ./components/HelloWorld.vue
<script setup lang="ts">
import { ref } from 'vue'
const msg = ref('Hello Vue3')

const handleChangeMsg = (v: string) => {
  msg.value = v
}

defineExpose({
  msg,
  handleChangeMsg
})
</script>

<template>
  <h1>{{ msg }}</h1>
</template>

使用组件:

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import HelloWorld from './components/HelloWorld.vue'
// 此处暂时使用any,需要定义类型
const root = ref<any>(null)

onMounted(() => {
  console.log(root.value.msg)
})

const handleChangeMsg = () => {
  root.value.handleChangeMsg('Hello TS')
}
</script>

<template>
  <HelloWorld ref="root" />
  <button @click="handleChangeMsg">handleChangeMsg</button>
</template>
————————

1 父组件传递给子组件

父组件通过v-bind绑定一个数据,然后子组件通过defineProps接受传过来的值。

<template>
    <div class="layout">
        <Menu v-bind:data="data"  title="我是标题"></Menu> // 传递字符串的时候可以不需要v-bind,传递非字符串类型需要加v-bind
        <div class="layout-right">
            <Header></Header>
            <Content></Content>
        </div>
    </div>
</template>
 
<script setup lang="ts">
import Menu from './Menu/index.vue'
import Header from './Header/index.vue'
import Content from './Content/index.vue'
import { reactive } from 'vue';
 
const data = reactive<number[]>([1, 2, 3])
</script>

子组件接受值,通过defineProps 来接受 defineProps是无须引入的直接使用即可

<template>
    <div class="menu">
        菜单区域 {{ title }}
        <div>{{ data }}</div>
    </div>
</template>
 
<script setup lang="ts">
defineProps<{
    title:string,
    data:number[]
}>()
</script>

TS特有的默认值方式

withDefaults是个函数也是无须引入开箱即用接受一个props函数第二个参数是一个对象设置默认值

type Props = {
    title?: string,
    data?: number[]
}
withDefaults(defineProps<Props>(), {
    title: "张三",
    data: () => [1, 2, 3]
})

2 子组件给父组件传参

是通过defineEmits派发一个事件。

<template>
    <div class="menu">
        <button @click="clickTap">派发给父组件</button>
    </div>
</template>
 
<script setup lang="ts">
import { reactive } from 'vue'
const list = reactive<number[]>([4, 5, 6])

const emit = defineEmits(['on-click'])
const clickTap = () => {
    emit('on-click', list)
}
</script>

我们在子组件绑定了一个click 事件 然后通过defineEmits 注册了一个自定义事件,点击click 触发 emit 去调用我们注册的事件 然后传递参数,父组件接受子组件的事件。

<template>
    <div class="layout">
        <Menu @on-click="getList"></Menu>
        <div class="layout-right">
            <Header></Header>
            <Content></Content>
        </div>
    </div>
</template>
 
<script setup lang="ts">
import Menu from './Menu/index.vue'
import Header from './Header/index.vue'
import Content from './Content/index.vue'
import { reactive } from 'vue';
 
const data = reactive<number[]>([1, 2, 3])
const getList = (list: number[]) => {
    console.log(list,'父组件接受子组件');
}
</script>

我们从Menu 组件接受子组件派发的事件on-click 后面是我们自己定义的函数名称getList,会把参数返回过来。

3 子组件暴露给父组件内部属性

在 中,默认不会暴露任何在 中声明的绑定,即不能通过模板 获取到组件实例声明的绑定。 提供了 编译器宏,可以显式地暴露需要暴露的组件中声明的变量和方法。

Vue3 
<script setup> 
ref
Vue3
defineExpose
// ./components/HelloWorld.vue
<script setup lang="ts">
import { ref } from 'vue'
const msg = ref('Hello Vue3')

const handleChangeMsg = (v: string) => {
  msg.value = v
}

defineExpose({
  msg,
  handleChangeMsg
})
</script>

<template>
  <h1>{{ msg }}</h1>
</template>

使用组件:

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import HelloWorld from './components/HelloWorld.vue'
// 此处暂时使用any,需要定义类型
const root = ref<any>(null)

onMounted(() => {
  console.log(root.value.msg)
})

const handleChangeMsg = () => {
  root.value.handleChangeMsg('Hello TS')
}
</script>

<template>
  <HelloWorld ref="root" />
  <button @click="handleChangeMsg">handleChangeMsg</button>
</template>