动态组件
使用场景:tab栏切换
一个盒子可以有固定类和动态类 :class="[active == index ? 'active' : '']
import AVue from './components/expame/A.vue'
const comId = ref(AVue)
<component :is="comId"></component>
插槽
子组件 Dialog
<div>
<div class="header">
<slot></slot>
</div>
<div class="main"></div>
<div class="footer"></div>
</div>
父组件
<Dialog>
<template v-slot>
<div>top</div>
</template>
</Dialog>
插槽写在子组件内
具名插槽
子组件
<div class="header">
<slot name="one"></slot>
</div>
<div class="main">
<slot name="two"></slot>
</div>
<div class="footer">
<slot name="three"></slot>
</div>
父组件
<Dialog>
<template v-slot:three>
<div>top</div>
</template>
</Dialog>
作用域插槽 子组件给父组件传递数据
子组件中
import {reactive} from 'vue'
type names = {
name: string,
age: number
}
const data = reactive<names[]>([{
name: 'xm',
age: 18
},
{
name: 'xdm',
age: 28
},
{
name: 'cxm',
age: 128
}
])
<div class="main">
<div v-for="item in data">
<slot name="three" :data="item"></slot>
</div>
</div>
父组件中
<Dialog>
<template v-slot:three="{data}">
<div>{{ data }}</div>
</template>
</Dialog>
动态插槽
子组件
<div class="footer">
<slot name="footer"></slot>
</div>
父组件
let name = ref('footer')
<Dialog>
<template #[name]>
<div>在哪</div>
</template>
</Dialog>
v-slot:three可以简写为 #three
v-slot 简写为 #default
异步组件
使用产场景:骨架屏(图片未加载出来前显示个默认图片,加载出来后再去填充)
父组件引入动态子组件需要一个方法 defineAsyncComponent
const SyncVue:any = defineAsyncComponent(() =>
import('./components/Sync.vue')
)
<Suspense>
<template #default>
<SyncVue></SyncVue>
</template>
<template #fallback>
<AVue></AVue>
</template>
</Suspense>
Suspense为内置组件
动态组件放#default里
代码分包 用异步组件方式就可以 打完包会出现多个包
打包后只有一个js文件,如果这个js文件过大那么首页加载白屏时间会非常长,代码分包就是将用不到的包先拆分出来,后面用到的组件不打到主包里去
传送组件
作用:将模板渲染进任何一个dom节点
<Teleport to="body">
<AVue></AVue>
</Teleport>
传到了body to后面跟的是选择器
keep-alive
<keep-alive :include="['']">
<AVue v-if="flag"></AVue>
<BVue v-else></BVue>
</keep-alive>
切换组件AB会缓存上一次的值
include支持 字符串 正则 数组 里面是缓存的名字 默认全部缓存
与之相反 还有exclude
开启keep-alive后会多出两个声明周期 onActivated和onDeactivated 分别在onMounted后和切换走时触发 (不加keep-alive的组件销毁时会走onUnMounted生命周期)
动画组件
使用场景:盒子隐藏消失时渐变效果
<transition name='fade'>
<div v-if='flag' class="box"></div>
</transition>
transiton为vue内置组件
组件上的name为fade 则css里类对应规则为
.box {
width: 200px;
height: 200px;
background-color: red;
}
.fade-enter-from {
width: 0;
height: 0;
background: red;
}
.fade-enter-active {
transition: all 3.5s linear;
}
.fade-enter-to {
width: 200px;
height: 200px;
background: red;
}
分别为前 时 后 .box放在最前(否则动画会失效 坑)
离开
.fade-leave-from {
width: 200px;
height: 200px;
}
.fade-leave-active {
transition: all 3s linear;
}
.fade-leave-to {
width: 0;
height: 0;
}
给transition组件添加命名类
<transition name='fade' enter-from-class="c-from">
<div v-if='flag' class="box"></div>
</transition>
// .fade-enter-from {
// width: 0;
// height: 0;
// background: pink;
// }
.c-from {
width: 0;
height: 0;
background: pink;
}
此时c-from就能替代fade-enter-from
动态css库
animate.css
使用方法
先安装animate.css库
cnpm i -S animate.css
要使用的组件中引用
import 'animate.css'
使用
<transition enter-active-class="animate__animated animate__fadeIn" leave-active-class="animate__animated animate__fadeOut">
<div v-if='flag' class="box"></div>
</transition>
例如加淡入淡出 animate__fadeIn animate__fadeOut 直接指令官网类名(前面添加animate__animated) 此时ransition组件上之前指定的name要去掉
单独定义动画时间 duration
<transition :duration="5000" enter-active-class="animate__animated animate__fadeIn" leave-active-class="animate__animated animate__fadeOut">
<div v-if='flag' class="box"></div>
</transition>
单独定义进入离开事件
:duration={enter: 500, leave: 600}
transition的生命周期
当涉及一些复杂的功能 计算 单纯的css就满足不了 此时需要js的生命周期完成
使用方法
<transition @before-enter="enterFrom">
<div v-if='flag' class="box"></div>
</transition>
const enterFrom = () => {
console.log('进入之前')
}
进入前 before-enter
进入活动时 enter
进入后 after-enter
进入过渡被打断 enter-cancelled
离开之前 before-leave
离开 leave
离开之后 after-leave
离开被打断 leave-cancelled
js动画库 gsap
官网地址 https://greensock.com/
安装 cnpm i -S gsap
引入
列表动画
<template>
<div class="content">
<button @click="flag = !flag">switch</button>
<button @click="add">add</button>
<button @click="pop">pop</button>
<div class="wrap">
<transition-group enter-active-class="animate__animated animate__bounce" leave-active-class="animate__animated animate__bounce">
<div class="item" :key="item" v-for="item in list">{{ item }}</div>
</transition-group>
</div>
</div>
</template>
const list = reactive<number[]>([1, 2, 3, 4, 5, 6])
const add = () => {
list.push(list.length + 1)
}
const pop = () => {
list.pop()
}
列表更新时就带动画了
状态动画过渡
表单值更新后有一个递增效果
借助gsap动画js库
<template>
<div>
<input type="number" step="20" v-model="num.current">
<div>{{ num.tweenNumber.toFixed(0) }}</div>
</div>
</template>
<script setup lang='ts'>
import { reactive, watch } from 'vue'
import gsap from 'gsap'
const num = reactive({
current: 0,
tweenNumber: 0
})
watch(
() => num.current,
newVal => {
gsap.to(num, {
duration: 1,
tweenNumber: newVal
})
}
)
</script>