Files

134 lines
3.6 KiB
JavaScript
Raw Permalink Normal View History

2026-02-10 08:05:03 +08:00
import { prefix } from '../common/config';
export default function transition() {
return {
data() {
return {
transitionClass: '',
transitionDurations: 300,
className: '',
realVisible: false,
};
},
props: {
visible: {
type: Boolean,
default: null,
},
appear: Boolean,
name: {
type: String,
default: 'fade',
},
durations: {
type: Number,
optionalTypes: [Array],
},
},
watch: {
visible: {
handler(val, oldVal) {
this.watchVisible(val, oldVal);
},
},
},
created() {
this.status = '';
this.transitionT = 0;
},
beforeMount() {
this.dataDurations = this.getDurations();
if (this.visible) {
this.enter();
}
this.inited = true;
},
destroyed() {
clearTimeout(this.transitionT);
},
methods: {
watchVisible(curr, prev) {
if (this.inited && curr !== prev) {
curr ? this.enter() : this.leave();
}
},
getDurations() {
const { durations } = this;
if (Array.isArray(durations)) {
return durations.map(item => Number(item));
}
return [Number(durations), Number(durations)];
},
enter() {
const { name, transitionDurations } = this;
const [duration] = this.dataDurations;
this.status = 'entering';
this.realVisible = true;
this.transitionClass = `${prefix}-${name}-enter ${prefix}-${name}-enter-active`;
setTimeout(() => {
this.transitionClass = `${prefix}-${name}-enter-active ${prefix}-${name}-enter-to`;
}, 30);
if (typeof duration === 'number' && duration > 0) {
this.transitionT = setTimeout(this.entered.bind(this), duration + 30);
} else {
this.transitionT = setTimeout(
this.status === 'leaving' ? this.leaved.bind(this) : (() => {}),
transitionDurations + 30,
);
}
},
entered() {
this.customDuration = false;
clearTimeout(this.transitionT);
this.status = 'entered';
this.transitionClass = '';
},
leave() {
const { name, transitionDurations } = this;
const [, duration] = this.dataDurations;
this.status = 'leaving';
this.transitionClass = `${prefix}-${name}-leave ${prefix}-${name}-leave-active`;
clearTimeout(this.transitionT);
setTimeout(() => {
this.transitionClass = `${prefix}-${name}-leave-active ${prefix}-${name}-leave-to`;
}, 30);
if (typeof duration === 'number' && duration > 0) {
this.customDuration = true;
this.transitionT = setTimeout(this.leaved.bind(this), duration + 30);
} else {
this.transitionT = setTimeout(
this.status === 'leaving' ? this.leaved.bind(this) : (() => {}),
transitionDurations + 30,
);
}
},
leaved() {
this.customDuration = false;
this.$emit('leaved');
clearTimeout(this.transitionT);
this.status = 'leaved';
this.transitionClass = '';
this.realVisible = false;
},
onTransitionEnd() {
if (this.customDuration) {
return;
}
clearTimeout(this.transitionT);
if (this.status === 'entering' && this.visible) {
this.entered();
} else if (this.status === 'leaving' && !this.visible) {
this.leaved();
}
},
},
};
}
export const transitionMixins = transition();