【第二章】

递归组件的使用

父组件代码

<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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值