大家好!我叫戴向天
QQ群:602504799
如若有不理解的,可加QQ群进行咨询了解
Tips: 是在Element-UI的基础上进行更改操作的,原有的Element-UI是不支持方向性的处理,以及动画时间的设定,并且还需要通过CSS进行动画处理,当前改造过的该组件不需要CSS,可以直接进行复制使用。
使用方法:
<Slider
:direction="sliderDirection"
:duration="duration"
>
<div style="width:50px;height:50px;background:red;position:absolute; top:0;" v-show="showSlider ">
点击收起/展开
<div>
</Slider>
<script setup lang="tsx">
import { ref } from "@vue/runtime-core";
// 动画时间
const duration = ref(3000)
// 动画方向
const sliderDirection = ref('top'); // 可选值: ["ltr", "rtl", "ttb", "btt", "left", "right", "top", "bottom"]
// 是否展开和显示
const showSlider = ref(true)
<script>
<template>
<transition
@beforeEnter="beforeEnter"
@enter="enter"
@afterEnter="afterEnter"
@beforeLeave="beforeLeave"
@leave="leave"
@afterLeave="afterLeave"
>
<slot />
</transition>
</template>
<script lang="ts">
import { defineComponent } from "@vue/runtime-core";
export default defineComponent({
name: "Slider",
props: {
duration: {
type: Number,
default: 300,
note: "收起展开的动画时间 毫秒 默认 300毫秒",
},
direction: {
type: String,
default: "ttb",
note: "打开方向,主要还是需要根据插槽元素的position进行处理,例如:bottom,则就需要css设置bottom:0",
types: {
string: ["ltr", "rtl", "ttb", "btt", "left", "right", "top", "bottom"],
},
},
},
computed: {
getColumns(): {
scroll: "scrollWidth" | "scrollHeight";
size: "width" | "height";
offset: 'offsetWidth' | 'offsetHeight',
padding: ["paddingLeft" | "paddingTop", "paddingRight" | "paddingBottom"];
oldPadding: string[];
} {
if (["left", "right", "ltr", "rtl"].includes(this.direction)) {
return {
scroll: "scrollWidth",
size: "width",
offset: 'offsetWidth',
padding: ["paddingLeft", "paddingRight"],
oldPadding: ["oldPaddingLeft", "oldPaddingRight"],
};
}
return {
scroll: "scrollHeight",
size: "height",
offset: 'offsetHeight',
padding: ["paddingTop", "paddingBottom"],
oldPadding: ["oldPaddingTop", "oldPaddingBottom"],
};
},
},
methods: {
beforeEnter(el: HTMLElement) {
el.style.transition = `all ${this.duration}ms`;
if (!el.dataset) {
(el as any).dataset = {};
}
el.dataset[this.getColumns.oldPadding[0]] = el.style[this.getColumns.padding[0]];
el.dataset[this.getColumns.oldPadding[1]] = el.style[this.getColumns.padding[1]];
el.style[this.getColumns.size] = "0";
el.style[this.getColumns.padding[0]] = "0";
el.style[this.getColumns.padding[1]] = "0";
this.$emit("beforeEnter");
},
enter(el: HTMLElement) {
el.dataset.oldOverflow = el.style.overflow;
// 该部分主要是用来获取元素的宽高
const cloneEl = el.cloneNode(true) as HTMLElement
cloneEl.style[this.getColumns.size] = '';
(el.parentNode as HTMLElement).appendChild(cloneEl)
const offset = cloneEl[this.getColumns.offset];
(el.parentNode as HTMLElement).removeChild(cloneEl)
if (el[this.getColumns.scroll] !== 0) {
el.style[this.getColumns.size] = `${offset}px`;
el.style[this.getColumns.padding[0]] = el.dataset[this.getColumns.oldPadding[0]] || "";
el.style[this.getColumns.padding[1]] = el.dataset[this.getColumns.oldPadding[1]] || "";
} else {
el.style[this.getColumns.size] = `${offset}px`;
el.style[this.getColumns.padding[0]] = el.dataset[this.getColumns.oldPadding[0]] || "";
el.style[this.getColumns.padding[1]] = el.dataset[this.getColumns.oldPadding[1]] || "";
}
el.style.overflow = "hidden";
this.$emit("enter");
},
afterEnter(el: HTMLElement) {
el.style.transition = "";
el.style[this.getColumns.size] = "";
el.style.overflow = el.dataset.oldOverflow || "";
this.$emit("afterEnter");
},
beforeLeave(el: HTMLElement) {
if (!el.dataset) {
(el as any).dataset = {};
}
el.dataset[this.getColumns.oldPadding[0]] =
el.style[this.getColumns.padding[0]];
el.dataset[this.getColumns.oldPadding[1]] =
el.style[this.getColumns.padding[1]];
el.dataset.oldOverflow = el.style.overflow;
el.style[this.getColumns.size] = `${el[this.getColumns.scroll]}px`;
el.style.overflow = "hidden";
this.$emit("beforeLeave");
},
leave(el: HTMLElement) {
if (el[this.getColumns.scroll] !== 0) {
el.style.transition = `all ${this.duration}ms`;
el.style[this.getColumns.size] = "0";
el.style[this.getColumns.padding[0]] = "0";
el.style[this.getColumns.padding[1]] = "0";
}
this.$emit("leave");
},
afterLeave(el: HTMLElement) {
el.style.transition = "";
el.style[this.getColumns.size] = "";
el.style.overflow = el.dataset.oldOverflow || "";
el.style[this.getColumns.padding[0]] =
el.dataset[this.getColumns.oldPadding[0]] || "";
el.style[this.getColumns.padding[1]] =
el.dataset[this.getColumns.oldPadding[1]] || "";
this.$emit("afterLeave");
},
},
});
</script>
</script>