diff --git a/packages/devui-vue/devui/back-top/src/back-top-types.ts b/packages/devui-vue/devui/back-top/src/back-top-types.ts
index 6f76d1cda94731627d7ff7f283a1370b35a56c66..1209ed581cdbdd9ab01fa60a170b9d5c3eeba582 100644
--- a/packages/devui-vue/devui/back-top/src/back-top-types.ts
+++ b/packages/devui-vue/devui/back-top/src/back-top-types.ts
@@ -1,7 +1,6 @@
import type { PropType, ExtractPropTypes } from 'vue'
export type Position = {
- position: 'fixed'
bottom: string
right: string
}
@@ -14,6 +13,14 @@ export const backTopProps = {
right: {
type: String,
default: '30px'
+ },
+ target: {
+ type: String,
+ default: 'window'
+ },
+ visibleHeight: {
+ type: Number,
+ default: 300
}
} as const
diff --git a/packages/devui-vue/devui/back-top/src/back-top.scss b/packages/devui-vue/devui/back-top/src/back-top.scss
index 18685214660f54b68cde866f7200e44b75ac0883..e0d28a369df11ffef577729591a0fdc34e4a9dd9 100644
--- a/packages/devui-vue/devui/back-top/src/back-top.scss
+++ b/packages/devui-vue/devui/back-top/src/back-top.scss
@@ -1,6 +1,7 @@
@import '../../styles-var/devui-var';
.devui-back-top {
+ position: fixed;
width: 40px;
height: 40px;
cursor: pointer;
@@ -8,12 +9,10 @@
.devui-back-top-base {
width: 40px;
height: 40px;
- box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
-
&:hover {
opacity: 1;
}
@@ -21,6 +20,7 @@
.devui-back-top-content {
opacity: 0.4;
background-color: $devui-text-weak;
+ box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
}
.devui-backtop-custom {
background-color: #fff;
diff --git a/packages/devui-vue/devui/back-top/src/back-top.tsx b/packages/devui-vue/devui/back-top/src/back-top.tsx
index f3b7314a37ef35f4bafc214c36100fb4d73aecdb..1939a4e0156f5d74c30d00b4159a0b0f7c12390b 100644
--- a/packages/devui-vue/devui/back-top/src/back-top.tsx
+++ b/packages/devui-vue/devui/back-top/src/back-top.tsx
@@ -1,6 +1,6 @@
-import { defineComponent } from 'vue'
+import { defineComponent, onMounted, ref } from 'vue'
import { backTopProps, BackTopProps } from './back-top-types'
-import { usePosition } from './hooks'
+import { usePosition, useVisibility } from './hooks'
import './back-top.scss'
import IconTop from './assets/top.svg'
@@ -9,11 +9,14 @@ export default defineComponent({
props: backTopProps,
emits: [],
setup(props: BackTopProps, ctx) {
- const position = usePosition(props)
const slots = ctx.slots
+ const backTopRef = ref(null)
+
+ const position = usePosition(props)
+ let isVisible = useVisibility(props, backTopRef)
const scrollToTop = () => {
- // 运行在浏览器则调用该方法
+ // toTop方法暂定
window &&
window.scrollTo({
top: 0,
@@ -24,13 +27,15 @@ export default defineComponent({
return () => (
void
+/* 简陋版待完善 */
+function useEventListener(target: HTMLElement, event: string, cb: cbFn) {
+ if (target) target.addEventListener(event, cb)
+}
+
+export default useEventListener
diff --git a/packages/devui-vue/devui/back-top/src/hooks/use-position.ts b/packages/devui-vue/devui/back-top/src/hooks/use-position.ts
index b7c80f161f86ed297e7faf125afdba93e01beeb6..c66c16d531b0dfed3caffae388a36632ad48e4a8 100644
--- a/packages/devui-vue/devui/back-top/src/hooks/use-position.ts
+++ b/packages/devui-vue/devui/back-top/src/hooks/use-position.ts
@@ -4,7 +4,6 @@ export default function (props: BackTopProps): Position {
const { bottom, right } = props
return {
- position: 'fixed',
bottom,
right
}
diff --git a/packages/devui-vue/devui/back-top/src/hooks/use-target.ts b/packages/devui-vue/devui/back-top/src/hooks/use-target.ts
new file mode 100644
index 0000000000000000000000000000000000000000..220e770bd7780759ce606729ef9200aa7d09b6a3
--- /dev/null
+++ b/packages/devui-vue/devui/back-top/src/hooks/use-target.ts
@@ -0,0 +1,19 @@
+import { BackTopProps } from '../back-top-types'
+
+export default function (props: BackTopProps, backTopRef) {
+ const target = props.target // target为元素选择器
+
+ const getTargetEl = () => {
+ const targetEl = document.querySelector(target)
+ if (!targetEl) throw new Error(`props ${target} is not existed`)
+
+ // 设置定位
+ targetEl.style.position = 'relative'
+ backTopRef.value.style.position = 'absolute'
+ return targetEl
+ }
+ const currTarget =
+ target === 'window' ? window || document.documentElement || document.body : getTargetEl()
+
+ return currTarget
+}
diff --git a/packages/devui-vue/devui/back-top/src/hooks/use-throttle.ts b/packages/devui-vue/devui/back-top/src/hooks/use-throttle.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ab5278fc31e2a37d9d94bad7965457cabf132047
--- /dev/null
+++ b/packages/devui-vue/devui/back-top/src/hooks/use-throttle.ts
@@ -0,0 +1,10 @@
+export default function (fn, delay) {
+ let last = null
+ return (...args) => {
+ const now = +Date.now()
+ if (now - last > delay) {
+ last = now
+ return fn.apply(this, args)
+ }
+ }
+}
diff --git a/packages/devui-vue/devui/back-top/src/hooks/use-visibility.ts b/packages/devui-vue/devui/back-top/src/hooks/use-visibility.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5dc7061f9505deb50b02dbdf85f19b35d5521e39
--- /dev/null
+++ b/packages/devui-vue/devui/back-top/src/hooks/use-visibility.ts
@@ -0,0 +1,21 @@
+import { onMounted, computed, ref } from 'vue'
+import { BackTopProps } from '../back-top-types'
+import { useTarget, useEventListener, useThrottle } from '.'
+export default function (props: BackTopProps, backTopRef) {
+ const visibleHeight = props.visibleHeight
+ const currScrollTop = ref(0)
+ const ThrottleCBFn = function () {
+ currScrollTop.value = currTarget === window ? window.pageYOffset : currTarget.scrollTop
+ }
+
+ let currTarget = null
+ onMounted(() => {
+ currTarget = useTarget(props, backTopRef)
+ // 监听滚动事件 手动更新ScrollTop
+ useEventListener(currTarget, 'scroll', useThrottle(ThrottleCBFn, 150))
+ })
+
+ const isVisible = computed(() => currScrollTop.value >= visibleHeight)
+
+ return isVisible
+}
diff --git a/packages/devui-vue/docs/components/back-top/index.md b/packages/devui-vue/docs/components/back-top/index.md
index f2be59b9ed7b38c1fab6fe7f25fb189add33c192..76cf74ff1a2ba398e10368702e5b615cc491e047 100644
--- a/packages/devui-vue/docs/components/back-top/index.md
+++ b/packages/devui-vue/docs/components/back-top/index.md
@@ -73,15 +73,80 @@ export default defineComponent({
:::
+### 嵌入容器内部
+
+通过设置 target 参数,可对特定容器进行返回顶部操作。
+
+:::demo
+
+```vue
+
+
+
+
+
+
+
+```
+
+:::
+
### d-back-top
d-back-top 参数
-| 参数 | 类型 | 默认 | 说明 | 跳转 Demo |
-| :----: | :------: | :----: | :------------------------: | :---------------: |
-| bottom | `string` | "50px" | 可选,按钮距离页面底部位置 | [示例](#基本用法) |
-| right | `string` | "30px" | 可选,按钮距离页面右边距 | [示例](#基本用法) |
-| | | | | |
+| 参数 | 类型 | 默认 | 说明 | 跳转 Demo |
+| :-----------: | :------: | :------: | :-------------------------------------------------------------------: | :-------------------: |
+| bottom | `string` | "50px" | 可选,按钮距离页面底部位置 | [示例](#基本用法) |
+| right | `string` | "30px" | 可选,按钮距离页面右边距 | [示例](#基本用法) |
+| visibleHeight | `number` | 300 | 可选,滚动高度达到 visibleHeight 所设值后展示回到顶部按钮,单位为`px` | [示例](#基本用法) |
+| target | `string` | 'window' | 可选,触发滚动的元素选择器 | [示例](#嵌入容器内部) |
+| | | | | |
d-back-top 事件