Skip to content

Commit 853f3d3

Browse files
author
zhigang.li
committed
增加ABackTop组件,支持在自定义滚动容器
1 parent 39e8fa7 commit 853f3d3

File tree

4 files changed

+132
-1
lines changed

4 files changed

+132
-1
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import ABackTop from './index.vue'
2+
export default ABackTop
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<template>
2+
<div :class="classes" :style="styles" @click="back">
3+
<slot>
4+
<div :class="innerClasses">
5+
<i class="ivu-icon ivu-icon-ios-arrow-up"></i>
6+
</div>
7+
</slot>
8+
</div>
9+
</template>
10+
<script>
11+
import { scrollTop } from '@/libs/util'
12+
import { on, off } from '@/libs/tools'
13+
const prefixCls = 'ivu-back-top'
14+
15+
export default {
16+
name: 'ABackTop',
17+
props: {
18+
height: {
19+
type: Number,
20+
default: 400
21+
},
22+
bottom: {
23+
type: Number,
24+
default: 30
25+
},
26+
right: {
27+
type: Number,
28+
default: 30
29+
},
30+
duration: {
31+
type: Number,
32+
default: 1000
33+
},
34+
container: {
35+
type: null,
36+
default: window
37+
}
38+
},
39+
data () {
40+
return {
41+
backTop: false
42+
}
43+
},
44+
mounted () {
45+
// window.addEventListener('scroll', this.handleScroll, false)
46+
// window.addEventListener('resize', this.handleScroll, false)
47+
on(this.containerEle, 'scroll', this.handleScroll)
48+
on(this.containerEle, 'resize', this.handleScroll)
49+
},
50+
beforeDestroy () {
51+
// window.removeEventListener('scroll', this.handleScroll, false)
52+
// window.removeEventListener('resize', this.handleScroll, false)
53+
off(this.containerEle, 'scroll', this.handleScroll)
54+
off(this.containerEle, 'resize', this.handleScroll)
55+
},
56+
computed: {
57+
classes () {
58+
return [
59+
`${prefixCls}`,
60+
{
61+
[`${prefixCls}-show`]: this.backTop
62+
}
63+
]
64+
},
65+
styles () {
66+
return {
67+
bottom: `${this.bottom}px`,
68+
right: `${this.right}px`
69+
}
70+
},
71+
innerClasses () {
72+
return `${prefixCls}-inner`
73+
},
74+
containerEle () {
75+
return this.container === window ? window : document.querySelector(this.container)
76+
}
77+
},
78+
methods: {
79+
handleScroll () {
80+
this.backTop = this.containerEle.scrollTop >= this.height
81+
},
82+
back () {
83+
let target = typeof this.container === 'string' ? this.containerEle : (document.documentElement || document.body)
84+
const sTop = target.scrollTop
85+
scrollTop(this.containerEle, sTop, 0, this.duration)
86+
this.$emit('on-click')
87+
}
88+
}
89+
}
90+
</script>

src/components/main/main.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
<keep-alive :include="cacheList">
2828
<router-view/>
2929
</keep-alive>
30+
<ABackTop :height="100" :bottom="80" :right="50" container=".content-wrapper"></ABackTop>
3031
</Content>
3132
</Layout>
3233
</Content>
@@ -38,6 +39,7 @@ import SideMenu from './components/side-menu'
3839
import HeaderBar from './components/header-bar'
3940
import TagsNav from './components/tags-nav'
4041
import User from './components/user'
42+
import ABackTop from './components/a-back-top'
4143
import Fullscreen from './components/fullscreen'
4244
import Language from './components/language'
4345
import ErrorStore from './components/error-store'
@@ -56,7 +58,8 @@ export default {
5658
TagsNav,
5759
Fullscreen,
5860
ErrorStore,
59-
User
61+
User,
62+
ABackTop
6063
},
6164
data () {
6265
return {

src/libs/util.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,39 @@ export const localSave = (key, value) => {
348348
export const localRead = (key) => {
349349
return localStorage.getItem(key) || ''
350350
}
351+
352+
// scrollTop animation
353+
export const scrollTop = (el, from = 0, to, duration = 500, endCallback) => {
354+
if (!window.requestAnimationFrame) {
355+
window.requestAnimationFrame = (
356+
window.webkitRequestAnimationFrame ||
357+
window.mozRequestAnimationFrame ||
358+
window.msRequestAnimationFrame ||
359+
function (callback) {
360+
return window.setTimeout(callback, 1000 / 60)
361+
}
362+
)
363+
}
364+
const difference = Math.abs(from - to)
365+
const step = Math.ceil(difference / duration * 50)
366+
367+
const scroll = (start, end, step) => {
368+
if (start === end) {
369+
endCallback && endCallback()
370+
return
371+
}
372+
373+
let d = (start + step > end) ? end : start + step
374+
if (start > end) {
375+
d = (start - step < end) ? end : start - step
376+
}
377+
378+
if (el === window) {
379+
window.scrollTo(d, d)
380+
} else {
381+
el.scrollTop = d
382+
}
383+
window.requestAnimationFrame(() => scroll(d, end, step))
384+
}
385+
scroll(from, to, step)
386+
}

0 commit comments

Comments
 (0)