diff --git a/example/docs/zh-CN/components/backtop.md b/example/docs/zh-CN/components/backtop.md index 7c8c7024..a1564478 100644 --- a/example/docs/zh-CN/components/backtop.md +++ b/example/docs/zh-CN/components/backtop.md @@ -1,12 +1,11 @@ ::: title 基础使用 -###### 回到顶部组件的默认样式,通过滑动来查看页面右下角的正方形按钮。 +###### 回到顶部组件的默认样式,lay-backtop 会自动寻找最近的可滚动祖先元素,也可以使用 target 属性指定触发滚动事件的元素,通过滑动来查看页面右下角的正方形按钮。 ::: ::: demo - ::: @@ -17,18 +16,17 @@ ::: demo - + @@ -53,7 +51,7 @@ export default { ::: title 滚动容器 -###### 通过设置 targetposition="absolute"参数 ,可对特定容器进行返回顶部操作 +###### 通过设置 targetposition="absolute"参数,可对特定容器进行返回顶部操作 ::: ::: demo @@ -94,7 +92,7 @@ export default { | opacity | 可选,不透明度 | number | 0.0-1.0 | | color | 可选,前景颜色 | string | #FFFFFF | | borderRadius | 可选,添加圆角 | string | 2px(默认) | -| circular | 可选, 使用圆形按钮 | boolean | true \| false(默认) +| circle | 可选, 使用圆形按钮 | boolean | true \| false(默认) | 图标样式 | | icon | 可选,图标类型 | string | layui-icon-top(默认) | | iconSize | 可选,图标大小 | number | 30 | diff --git a/src/module/backTop/index.vue b/src/module/backTop/index.vue index 66c8bee8..256a0a1a 100644 --- a/src/module/backTop/index.vue +++ b/src/module/backTop/index.vue @@ -43,7 +43,7 @@ export interface LayBacktopProps { opacity?: number; color?: string; borderRadius?: number | string; - circular?: boolean; + circle?: boolean; /**图标样式*/ icon?: string; iconSize?: number; @@ -54,13 +54,11 @@ export interface LayBacktopProps { const props = withDefaults(defineProps(), { target: 'window', showHeight: 200, - right: 30, - bottom: 40, icon: 'layui-icon-top', iconSize: 30, iconPrefix: 'layui-icon', disabled: false, - circular: false, + circle: false, }); const emit = defineEmits(['click']); @@ -70,7 +68,7 @@ const scrollTarget = shallowRef(undefined); let visible = ref(props.showHeight === 0); const borderRadius = computed(() => { - if (props.circular) return "50%"; + if (props.circle) return "50%"; return typeof props.borderRadius === 'number' ? `${props.borderRadius}px` : props.borderRadius; }); @@ -86,6 +84,7 @@ const styleBacktop = computed(() => { } }); +// TODO 待改进 const easeInOut = (value: number): number => { return value < 0.5 ? 2 * value * value : 1 - 2 * (value - 1) * (value - 1); } @@ -135,7 +134,7 @@ const handlerMouseup = () => { // 获取滚动目标元素 const getScrollTarget = () => { if (props.target === 'window') { - return window || document.documentElement || document.body; + return getScrollParent(backtopRef.value!, false); } else { const targetElement = document.querySelector(props.target); if (!targetElement) throw new Error(`target is not existed: ${props.target}`); @@ -147,8 +146,23 @@ const getScrollTarget = () => { } return targetElement; } -}; +} +// 获取距离元素最近的可滚动祖先元素 +const getScrollParent = (element: HTMLElement, includeHidden: boolean): HTMLElement => { + let style: CSSStyleDeclaration = getComputedStyle(element); + let excludeStaticParent: boolean = style.position === "absolute"; + let overflowRegex: RegExp = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/; + //if (style.position === "fixed") return document.documentElement || document.body || window; + for (let parent: HTMLElement = element; (parent = parent.parentElement!);) { + style = getComputedStyle(parent); + if (excludeStaticParent && style.position === "static") continue; + if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) return parent; + } + return document.documentElement || document.body || window; +} + +// 节流 const throttle = (func: Function, wait: number) => { var timer: any = null; return (...args: any) => { @@ -158,10 +172,11 @@ const throttle = (func: Function, wait: number) => { func.apply(this, args); }, wait); } - }; + } } onMounted(() => { + if (!props.target) return; scrollTarget.value = getScrollTarget(); scrollTarget.value.addEventListener('scroll', throttle(handleScroll, 300)); });