增加ABackTop组件,支持在自定义滚动容器
This commit is contained in:
parent
39e8fa75f6
commit
853f3d3fb8
|
|
@ -0,0 +1,2 @@
|
||||||
|
import ABackTop from './index.vue'
|
||||||
|
export default ABackTop
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
<template>
|
||||||
|
<div :class="classes" :style="styles" @click="back">
|
||||||
|
<slot>
|
||||||
|
<div :class="innerClasses">
|
||||||
|
<i class="ivu-icon ivu-icon-ios-arrow-up"></i>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { scrollTop } from '@/libs/util'
|
||||||
|
import { on, off } from '@/libs/tools'
|
||||||
|
const prefixCls = 'ivu-back-top'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ABackTop',
|
||||||
|
props: {
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 400
|
||||||
|
},
|
||||||
|
bottom: {
|
||||||
|
type: Number,
|
||||||
|
default: 30
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
type: Number,
|
||||||
|
default: 30
|
||||||
|
},
|
||||||
|
duration: {
|
||||||
|
type: Number,
|
||||||
|
default: 1000
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
type: null,
|
||||||
|
default: window
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
backTop: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
// window.addEventListener('scroll', this.handleScroll, false)
|
||||||
|
// window.addEventListener('resize', this.handleScroll, false)
|
||||||
|
on(this.containerEle, 'scroll', this.handleScroll)
|
||||||
|
on(this.containerEle, 'resize', this.handleScroll)
|
||||||
|
},
|
||||||
|
beforeDestroy () {
|
||||||
|
// window.removeEventListener('scroll', this.handleScroll, false)
|
||||||
|
// window.removeEventListener('resize', this.handleScroll, false)
|
||||||
|
off(this.containerEle, 'scroll', this.handleScroll)
|
||||||
|
off(this.containerEle, 'resize', this.handleScroll)
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
classes () {
|
||||||
|
return [
|
||||||
|
`${prefixCls}`,
|
||||||
|
{
|
||||||
|
[`${prefixCls}-show`]: this.backTop
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
styles () {
|
||||||
|
return {
|
||||||
|
bottom: `${this.bottom}px`,
|
||||||
|
right: `${this.right}px`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
innerClasses () {
|
||||||
|
return `${prefixCls}-inner`
|
||||||
|
},
|
||||||
|
containerEle () {
|
||||||
|
return this.container === window ? window : document.querySelector(this.container)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleScroll () {
|
||||||
|
this.backTop = this.containerEle.scrollTop >= this.height
|
||||||
|
},
|
||||||
|
back () {
|
||||||
|
let target = typeof this.container === 'string' ? this.containerEle : (document.documentElement || document.body)
|
||||||
|
const sTop = target.scrollTop
|
||||||
|
scrollTop(this.containerEle, sTop, 0, this.duration)
|
||||||
|
this.$emit('on-click')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
<keep-alive :include="cacheList">
|
<keep-alive :include="cacheList">
|
||||||
<router-view/>
|
<router-view/>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
|
<ABackTop :height="100" :bottom="80" :right="50" container=".content-wrapper"></ABackTop>
|
||||||
</Content>
|
</Content>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
@ -38,6 +39,7 @@ import SideMenu from './components/side-menu'
|
||||||
import HeaderBar from './components/header-bar'
|
import HeaderBar from './components/header-bar'
|
||||||
import TagsNav from './components/tags-nav'
|
import TagsNav from './components/tags-nav'
|
||||||
import User from './components/user'
|
import User from './components/user'
|
||||||
|
import ABackTop from './components/a-back-top'
|
||||||
import Fullscreen from './components/fullscreen'
|
import Fullscreen from './components/fullscreen'
|
||||||
import Language from './components/language'
|
import Language from './components/language'
|
||||||
import ErrorStore from './components/error-store'
|
import ErrorStore from './components/error-store'
|
||||||
|
|
@ -56,7 +58,8 @@ export default {
|
||||||
TagsNav,
|
TagsNav,
|
||||||
Fullscreen,
|
Fullscreen,
|
||||||
ErrorStore,
|
ErrorStore,
|
||||||
User
|
User,
|
||||||
|
ABackTop
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -348,3 +348,39 @@ export const localSave = (key, value) => {
|
||||||
export const localRead = (key) => {
|
export const localRead = (key) => {
|
||||||
return localStorage.getItem(key) || ''
|
return localStorage.getItem(key) || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scrollTop animation
|
||||||
|
export const scrollTop = (el, from = 0, to, duration = 500, endCallback) => {
|
||||||
|
if (!window.requestAnimationFrame) {
|
||||||
|
window.requestAnimationFrame = (
|
||||||
|
window.webkitRequestAnimationFrame ||
|
||||||
|
window.mozRequestAnimationFrame ||
|
||||||
|
window.msRequestAnimationFrame ||
|
||||||
|
function (callback) {
|
||||||
|
return window.setTimeout(callback, 1000 / 60)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const difference = Math.abs(from - to)
|
||||||
|
const step = Math.ceil(difference / duration * 50)
|
||||||
|
|
||||||
|
const scroll = (start, end, step) => {
|
||||||
|
if (start === end) {
|
||||||
|
endCallback && endCallback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let d = (start + step > end) ? end : start + step
|
||||||
|
if (start > end) {
|
||||||
|
d = (start - step < end) ? end : start - step
|
||||||
|
}
|
||||||
|
|
||||||
|
if (el === window) {
|
||||||
|
window.scrollTo(d, d)
|
||||||
|
} else {
|
||||||
|
el.scrollTop = d
|
||||||
|
}
|
||||||
|
window.requestAnimationFrame(() => scroll(d, end, step))
|
||||||
|
}
|
||||||
|
scroll(from, to, step)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue