递归组件的使用
父组件代码
<template>
<Tree :data="treeList"></Tree>
</template>
<script setup lang="ts">
import Tree from './components/Tree.vue'
import { reactive } from 'vue'
// import Card from '@/components/Card.vue'
interface Tree {
name: string
checked: boolean
children?: Tree[]
}
const treeList = reactive<Tree[]>([
{ name: '1', checked: false, children: [{ name: '1-1', checked: false }] },
{
name: '2',
checked: false,
children: [
{ name: '2-1', checked: false },
{ name: '2-2', checked: false }
]
},
{
name: '3',
checked: false,
children: [
{
name: '3-1',
checked: false,
children: [{ name: '3-1-1', checked: false }]
}
]
}
])
</script>
子组件代码
<template>
<div
v-for="(item, i) in data"
:key="i"
class="tree"
@click.stop="checkItem(item, $event)"
>
<input type="checkbox" v-model="item.checked" />
<span>{{ item.name }}</span>
// 组件内使用组件本身
<Tree v-if="item.checked && item.children" :data="item.children"></Tree>
</div>
</template>
<script setup lang="ts">
export interface Tree {
name: string
checked: boolean
children?: Tree[]
}
defineProps<{
data?: Tree[]
}>()
</script>
实现效果:
动态组件 component
is属性指定要展示的组件
<component :is="vueCom"></component>
异步组件
defineAsyncComponent 与 Suspense 配合使用
<template>
<Suspense>
// 默认组件展示
<template #default>
<Msg></Msg>
</template>
// 默认组件未加载完成显示的内容
<template #fallback>
<Loading></Loading>
</template>
</Suspense>
</template>
<script setup lang="ts">
import Loading from '@/components/Loading.vue'
import { defineAsyncComponent } from 'vue'
const Msg = defineAsyncComponent(() => import('@/components/Msg.vue'))
</script>
插槽
定义一个插槽
<slot name="footer"></slot>
使用插槽: v-slot(简写:#)
<!-- <template v-slot:footer>
{{ msg }}
</template> -->
<template #footer>
{{ msg }}
</template>
子组件代码:
<template>
<div class="box">
<header>
//作用域插槽
<slot name="header" :data="data"></slot>
</header>
<section>
//默认插槽
<slot name="default"></slot>
</section>
<footer>
//命名插槽
<slot name="footer"></slot>
</footer>
</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
type data = {
id: number
msg: string
}
const data = reactive<data[]>([
{ id: 1, msg: '消息1' },
{ id: 2, msg: '消息2' },
{ id: 3, msg: '消息3' }
])
</script>
父组件代码:
<template>
<SlotVue>
// # v-slot缩写
<template #header="{ data }">
<div v-for="item of data">{{ item.id }}---{{ item.msg }}</div>
</template>
<template #default>
{{ msg }}
</template>
<template #footer>
{{ msg }}
</template>
</SlotVue>
</template>
<script setup lang="ts">
import SlotVue from '@/components/SlotVue.vue'
const msg = '我是被插入的内容'
效果:
Teleport传送
disabled: 默认为 false(生效) ,控制 to属性是否生效
to: 将标签内内容传送的位置(选择器)
<template>
<div class="parent">
<Teleport :disabled="false" to="body">
<DialogVue></DialogVue>
</Teleport>
</div>
</template>
<script setup lang="ts">
import DialogVue from './components/Dialog.vue'
</script>
keepAlive 组件缓存
include: 指定要被缓存的组件
exclude:指定不要被缓存的组件
被缓存的组件可以使用两个生命周期:
onActivated:组件被激活时调用
onDeactivated:组件被缓存时调用
子组件:
onActivated(() => {
console.log('A组件被激活了')
})
onDeactivated(() => {
console.log('A组件被缓存了')
})
父组件:
<template>
<button @click="showVue = A">A组件</button>
<button @click="showVue = B">B组件</button>
<KeepAlive include="A">
<component :is="showVue"></component>
</KeepAlive>
</template>
<script setup lang="ts">
import A from '@/components/A.vue'
import B from '@/components/B.vue'
import { shallowRef } from 'vue'
const showVue = shallowRef(A)
</script>
transition 与 transitionGroup
transiton结合animate.css库
<template>
<button @click="flag = !flag">切换</button>
<Transition
appear
appear-active-class="animate__animated animate__bounceIn"
enter-active-class="animate__animated animate__bounceIn"
leave-active-class="animate__animated animate__bounceOutUp"
name="fade"
>
<div class="box" v-show="flag"></div>
</Transition>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const flag = ref(true)
</script>
<style scoped>
.box {
margin: 20px;
width: 200px;
height: 200px;
background-color: aqua;
}
/* vue自带动画效果 */
/* .fade-enter-from {
width: 0;
height: 0;
}
.fade-enter-active {
transition: all 1s linear;
}
.fade-enter-to {
width: 200px;
height: 200px;
}
.fade-leave-from {
width: 200px;
height: 200px;
}
.fade-leave-active {
transition: all 2s linear;
}
.fade-leave-to {
width: 0;
height: 0;
} */
</style>
transitionGroup 一般对列表使用
tag:将transitionGroup渲染成指定元素节点
<TransitionGroup
enter-active-class="animate__animated animate__bounceIn"
leave-active-class="animate__animated animate__bounceOutUp"
>
<!-- 注意唯一标识 -->
<div :key="item" v-for="item of list">{{ item }}</div>
</TransitionGroup>