一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
父组件向子组件传值
子组件接收值时使用defineProps进行接收
-
字符串类型传值
当传值类型为基本数据类型时不需要使用
v-bind进行绑定。 -
数组等复杂数据类型类型传值
当传值类型为复杂数据类型时,这时时需要使用
v-bind进行绑定的。 父组件
<template>
<div>
<Main title="jxx" :data="list"></Main>
</div>
</template>
<script setup lang="ts">
// vue3只需要引用,不需要注册
import Main from './main.vue'
const list = reactive<number[]>([1,2,3,4])
</script>
子组件
<template>
<div>{{title}}</div>
<div>{{data}}</div>
</template>
<script setup lang="ts">
type Tit = {
title: string,
data: number[]
}
defineProps<Tit> ()
</script>
子组件通过事件向父组件进行传值
子组件向父组件传值使用defineEmits方法,这个函数里面接收一个数组,数组里面是需要传到外面的事件名称,可以有多个事件名称。
子组件向父组件可以传递多个值,只要在子组件接收时定义好相应的接收参数即可。
父组件
<template>
<div>
<Main title="jxx" :data="list" @click-data="getData"></Main>
</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import Main from './main.vue'
const list = reactive<number[]>([1,2,3,4])
const getData = (e:number[]) => {
console.log(e)
}
</script>
子组件
<template>
<button @click="handleClick"></button>
</template
<script setup lang="ts">
import { reactive } from 'vue'
const list = reactive<number[]>([2,3,4,5]);
type Tit = {
title: string,
data: number[]
}
defineProps<Tit> ()
// 子组件向父组件传递参数
const emit = defineEmits(['click-data']);
const handleClick = () => {
// 此处数据可以传多个参数
emit('click-data', list)
}
</script>
获取子组件的实例
通过ref的value值去获取子组件的实例,但是子组件什么也不会暴露出来,所以我们这时候需要在子组件中使用一个参数defineExpose将数据进行派发暴露,这样父组件就可以拿到子组件中的数据,至于vue3为什么要这样做呢,当然也是为了更加安全,父组件也就不能直接修改子组件的值,在vue2中父组件是可以直接修改子组件的值的。
父组件
<template>
<div>
<Main ref="jxx" title="jxx" :data="list" @click-data="getData"></Main>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import Main from './main.vue'
const list = reactive<number[]>([1,2,3,4]);
// 此处定义的值需要与标签中的ref的值保持一致
const jxx = ref(null);
const getData = (e:number[]) => {
console.log(jxx.value);
}
</script>
子组件
<template>
<div>{{title}}</div>
<div>{{data}}</div>
<button @click="handleClick"></button>
</template
<script setup lang="ts">
import { reactive } from 'vue'
const list = reactive<number[]>([2,3,4,5]);
type Tit = {
title: string,
data: number[]
}
defineProps<Tit> ()
const emit = defineEmits(['click-data']);
const handleClick = () => {
emit('click-data', list)
}
// 父组件需要获取的数据
defineExpose({
list
})
</script>
子组件默认值
子组件中通过withDefaults来定义默认值,此参数只支持ts
父组件
<template>
<div>
<Main></Main>
</div>
</template>
<script setup lang="ts">
import Main from './main.vue'
</script>
子组件
<template>
<div>{{title}}</div>
<div>{{data}}</div>
</template>
<script setup lang="ts">
type Tit = {
title?: string,
data?: number[]
}
withDefaults(defineProps<Tit> (), {
title: '默认值',
// data是一个复杂数据类型,需要通过一个函数来定义默认值
data:() => [1,2,3]
})
</script>
定义全局组件
如果需要定义全局组件,需要在main.ts中引用并注册该组件。
import Modal from './components/Modal/modal.vue'
creatApp(App).component('Modal', Modal).mount('#app');
简单的递归组件
使用场景:不确定的层级的树形结构。其主要原理就是子组件中调用自身组件
父组件
<template>
<div>
<Tree :data="data"></Tree>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import Tree from './main.vue'
type TreeList = {
name: string;
icon?: string;
children?: TreeList[] | [];
};
const data = reactive<TreeList[]>([
{
name: "no.1",
children: [
{
name: "no.1-1",
children: [
{
name: "no.1-1-1",
},
],
},
],
},
{
name: "no.2",
children: [
{
name: "no.2-1",
},
],
},
{
name: "no.3",
},
]);
</script>
子组件
<template>
<div style="margin-left:10px;" class="tree">
<div :key="index" v-for="(item,index) in data">
<div>{{item.name}}
</div>
// 这里调用的组件就是此子组件本身
<TreeItem v-if='item?.children?.length' :data="item.children"></TreeItem>
</div>
</div>
</template>
<script setup lang="ts">
type TreeList = {
name: string;
icon?: string;
children?: TreeList[] | [];
};
type Props<T> = {
data?: T[] | [];
};
defineProps<Props<TreeList>>();
</script>
// 因为是子组件本身调用自己,所以需要给改文件定义一个名字
<script lang="ts">
export default {
name: "TreeItem"
}
</script>