【uniapp】如何封装一个好用的动画组件
[!TIP]
本篇主要讲述如何将
animate.css
在uniapp
中封装为一个动画组件方便后续开发使用
前言
相信很多小伙伴在开发过程中,总会被要求增加一些动画来使得页面更新美观,所以很多小伙伴都会直接使用各种各样的动画样式库,来满足开发需求。我也在开发中发现有时候光用v-if
确实有些不太美观,所以由此想基于animate.css
封装一个组件,以代替v-if
或者v-show
来展示,让页面更加具有美感。
准备阶段
首先就是要先下载animate.css
,uniapp
除非使用cli
开发,可以直接使用npm
安装,用HBX
开发就只能下载css文件了。不过我专门将其上传到了插件市场(见文末),方便小伙伴们下载。下载完后就可以进行下一步了
开发阶段
首先因为我使用动画组件是为了替代v-if
或 v-show
,所以在props中设计了俩个动画类,即展示时的动画类和隐藏时的动画类。然后加上animate.css
本身的一些属性,由此可以简单的设计为下面的参数。
export default {
//加载动画的显隐
show: {
type: Boolean,
default: false,
},
//入场动画
entryClass: {
type: String,
default: "animate__fadeIn",
},
//退场动画
exitClass: {
type: String,
default: "animate__fadeOut",
},
//持续时间
duration: {
type: Number,
default: 1000,
},
//延迟时间
delay: {
type: Number,
default: 0,
},
//自定义样式
customStyle: {
type: Object,
default: () => {},
},
};
其次就是在这个组件关闭时,我想要的效果是动画加载完毕后再进行隐藏,所以props.show
这个字段我们不能直接使用,想要进行一个延迟的操作。
const delayShow = ref(false);
const timer = shallowRef(null);
watch(
() => props.show,
(newVal) => {
if (timer.value) clearTimeout(timer.value);
if (newVal) {
delayShow.value = newVal;
emit("open");
timer.value = setTimeout(
() => {
emit("opened");
},
props.entryClass ? props.duration + props.delay : 0
);
} else {
emit("close");
timer.value = setTimeout(
() => {
delayShow.value = newVal;
emit("closed");
},
props.exitClass ? props.duration + props.delay : 0
);
}
},
{
immediate: true,
}
);
至此,核心思路已经封装完毕了。还是比较符合我的预想的。
完整代码
<template>
<view
v-show="delayShow"
:class="`animate__animated ${show ? entryClass : exitClass}`"
:style="{
...customStyle,
'--animate-duration': `${duration}ms`,
'--animate-delay': `${delay}ms`,
}"
>
<slot />
</view>
</template>
<script setup>
import { shallowRef, ref, watch } from "vue";
import TransitionAnimationProps from "./props.js";
const emit = defineEmits(["open", "close", "opened", "closed"]);
const props = defineProps({
...TransitionAnimationProps,
});
const delayShow = ref(false);
const timer = shallowRef(null);
watch(
() => props.show,
(newVal) => {
if (timer.value) clearTimeout(timer.value);
if (newVal) {
delayShow.value = newVal;
emit("open");
timer.value = setTimeout(
() => {
emit("opened");
},
props.entryClass ? props.duration + props.delay : 0
);
} else {
emit("close");
timer.value = setTimeout(
() => {
delayShow.value = newVal;
emit("closed");
},
props.exitClass ? props.duration + props.delay : 0
);
}
},
{
immediate: true,
}
);
</script>
<style scoped>
@import "animate.css";
</style>
小伙伴们,可以试试我在插件市场发布的r-animation组件。更多组件 完整文档
结语
我是iRainna,一个微末道行也想助力各位道友的前端er。