sard-uniapp
Version:
sard-uniapp 是一套基于 Uniapp + Vue3 框架开发的兼容多端的 UI 组件库
138 lines (137 loc) • 4.03 kB
JavaScript
import { ref, onMounted, onUnmounted, watch, computed } from 'vue';
const tickInterval = 30;
export function useTransition(options = {}) {
const duration = computed(() => {
return options.duration || 0;
});
const enterFromClass = computed(() => {
return options.enterFromClass || `${options.prefix}enter-from`;
});
const enterActiveClass = computed(() => {
return options.enterActiveClass || `${options.prefix}enter-active`;
});
const enterToClass = computed(() => {
return options.enterToClass || `${options.prefix}enter-to`;
});
const leaveFromClass = computed(() => {
return options.leaveFromClass || `${options.prefix}leave-from`;
});
const leaveActiveClass = computed(() => {
return options.leaveActiveClass || `${options.prefix}leave-active`;
});
const leaveToClass = computed(() => {
return options.leaveToClass || `${options.prefix}leave-to`;
});
const realVisible = ref(false);
const transitionClass = ref('');
let status = '';
let timer;
let tickTimer;
function nextTick(callback) {
tickTimer = setTimeout(() => {
tickTimer = null;
callback();
}, tickInterval);
}
function clearAllTimeout() {
if (tickTimer) {
clearTimeout(tickTimer);
tickTimer = null;
}
if (timer) {
clearTimeout(timer);
timer = null;
}
}
function callHook(name) {
options.onVisibleHook?.(name);
}
function enter() {
clearAllTimeout();
if (status === 'leaving') {
callHook('leave-cancelled');
}
status = 'entering';
realVisible.value = true;
transitionClass.value = `${enterFromClass.value} ${enterActiveClass.value}`;
callHook('before-enter');
nextTick(() => {
transitionClass.value = `${enterActiveClass.value} ${enterToClass.value}`;
callHook('enter');
});
timer = setTimeout(() => {
timer = null;
if (status === 'entering' && options.visible) {
entered();
}
}, duration.value + tickInterval);
}
function entered() {
clearAllTimeout();
status = 'entered';
transitionClass.value = '';
callHook('after-enter');
}
function leave() {
clearAllTimeout();
if (status === 'entering') {
callHook('enter-cancelled');
}
status = 'leaving';
transitionClass.value = `${leaveFromClass.value} ${leaveActiveClass.value}`;
callHook('before-leave');
nextTick(() => {
transitionClass.value = `${leaveActiveClass.value} ${leaveToClass.value}`;
callHook('leave');
});
timer = setTimeout(() => {
timer = null;
if (status === 'leaving' && !options.visible) {
leaved();
}
}, duration.value + tickInterval);
}
function leaved() {
clearAllTimeout();
status = 'leaved';
transitionClass.value = '';
realVisible.value = false;
callHook('after-leave');
}
function onTransitionEnd() {
if (status === 'entering' && options.visible) {
entered();
}
else if (status === 'leaving' && !options.visible) {
leaved();
}
}
onMounted(() => {
if (options.visible) {
enter();
}
});
onUnmounted(() => {
if (timer) {
clearTimeout(timer);
timer = null;
}
if (tickTimer) {
clearTimeout(tickTimer);
tickTimer = null;
}
});
watch(() => options.visible, () => {
if (options.visible) {
enter();
}
else {
leave();
}
});
return {
onTransitionEnd,
realVisible,
transitionClass,
};
}