绩效考核手机版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

174 lines
4.8 KiB

<template>
<view
:id="$sUid"
class="s-transition"
:class="c_class"
:style="c_style"
@animationend="onAnimationend"
>
<slot />
</view>
</template>
<script>
import componentMixin from '../../mixins/componentMixin';
/**
* s-transition 动画
* @description 用来控制一个元素显示隐藏时的动画
* @property {Boolean} value v-model双向绑定显示隐藏
* @property {String|Object|Boolean} name = [false|fade-top|slide-top|{enter:'fade',leave:'fade-top'}] 过渡效果 ,为s-ui styles下animate.scss中定义的效果
* @property {Number|String|Object} duration 动画执行时间
* @property {String} enterClass 进入过渡时自定义class
* @property {String} leaveClass 离开过渡时自定义class
* @event {Function} before-enter 进入过渡的开始前触发
* @event {Function} enter 进入过渡时触发
* @event {Function} before-leave 离开过渡的开始前触发
* @event {Function} leave 离开过渡时触发
* @example <s-transition v-model="visible"></s-transition>
*/
export default {
name: 'STransition',
mixins: [componentMixin],
props: {
value: Boolean,
name: {
type: [String, Object, Boolean],
default: 'fade',
},
duration: {
type: [Number, String, Object],
default: 300,
},
namePrefix: {
type: String,
default: 's-animate',
},
enterClass: String,
leaveClass: String,
},
data: () => ({
animateStatus: '',
isVisible: false,
}),
computed: {
c_class() {
const { animateStatus, namePrefix, custom_class } = this;
const animateName = this.animateStatus ? this.animateMap[this.animateStatus].name : '';
const animateClass = animateName ? `${namePrefix ? namePrefix + '-' : ''}${animateName}-${this.animateStatus}` : '';
return this.$mergeClass(
{
's-transition--enter': animateStatus === 'enter',
's-transition--leave': animateStatus === 'leave',
},
animateClass,
animateStatus === 'enter' ? this.enterClass : '',
animateStatus === 'leave' ? this.leaveClass : '',
custom_class,
);
},
c_style() {
return this.$mergeStyle({
animationDuration: this.animateStatus ? this.animateMap[this.animateStatus].duration + 'ms' : '',
display: this.isVisible ? '' : 'none',
}, this.custom_style);
},
animateMap() {
let animate = this.name;
let duration = this.duration;
if (this.$getType(animate) !== 'object') {
animate = { enter: animate, leave: animate };
}
if (this.$getType(duration) !== 'object') {
duration = { enter: duration, leave: duration };
}
return {
enter: {
name: animate.enter,
duration: parseInt(animate.enter ? duration.enter : 0) || 0,
},
leave: {
name: animate.leave,
duration: parseInt(animate.leave ? duration.leave : 0) || 0,
},
};
},
},
watch: {
value() {
this.updateVisible();
},
},
created() {
Object.assign(this, {
visibleStatus: false,
animationendCallback: null,
});
},
mounted() {
this.updateVisible();
},
beforeDestroy() {
this.removeAnimationendCallback();
},
methods: {
updateVisible() {
if (this._isMounted && this.visibleStatus !== this.value) {
this[this.value ? 'show' : 'hide']();
}
},
setAnimationendCallback(callback, duration) {
if (duration > 0) {
this.animationendCallback = callback;
} else {
callback();
}
},
removeAnimationendCallback() {
if (this.animationendCallback) {
this.animationendCallback = null;
}
},
onAnimationend(e) {
if (e.target.id === this.$sUid && this.animationendCallback) {
this.animationendCallback();
this.animationendCallback = null;
}
},
show() {
if (!this.visibleStatus) {
this.removeAnimationendCallback();
this.visibleStatus = true;
this.animateStatus = 'enter';
this.isVisible = true;
this.$emit('input', true);
this.$emit('before-enter');
this.setAnimationendCallback(() => {
this.animateStatus = '';
this.$emit('enter');
}, this.animateMap.enter.duration);
}
},
hide() {
if (this.visibleStatus) {
this.removeAnimationendCallback();
this.visibleStatus = false;
this.animateStatus = 'leave';
this.$emit('input', false);
this.$emit('before-leave');
this.setAnimationendCallback(() => {
this.isVisible = false;
this.zIndexValue = 0;
this.animateStatus = '';
this.$emit('leave');
}, this.animateMap.leave.duration);
}
},
},
};
</script>
<style lang="scss" src="./index.scss"></style>