Files
hoc-element-affix/src/components/ScrollAffix/index.vue
wangwenzhang c01cde6c20 init project
2020-04-03 16:34:17 +08:00

86 lines
1.9 KiB
Vue

<template>
<div
ref="scroll-affix"
:style="affixStyle"
class="scroll-affix-container"
>
<slot/>
</div>
</template>
<script>
export default {
name: 'Affix',
props: {
offsetTop: {
type: Number,
default: 0
}
},
data () {
return {
affixStyle: {
position: 'absolute',
top: 'initial'
},
instance: '',
defaultInstancePosition: ''
}
},
mounted () {
this.$nextTick(() => {
this.instance = this.$refs['scroll-affix']
this.createAffix()
})
},
methods: {
getInstanceRect () {
return this.instance.getBoundingClientRect()
},
getWindowScrollTop () {
return window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop
},
createAffix () {
this.defaultInstancePosition = this.getInstanceRect().top
this.beforeListener()
document.addEventListener('scroll', this.scrollListener)
},
setFixedForInstance () {
this.affixStyle = {
position: 'fixed',
top: `${this.offsetTop}px`
}
},
beforeListener () {
if (this.defaultInstancePosition < this.offsetTop) {
this.setFixedForInstance()
}
this.defaultInstancePosition = this.getWindowScrollTop() + this.defaultInstancePosition
},
scrollListener () {
const offsetTop = this.getInstanceRect().top
const windowScrollTop = this.getWindowScrollTop()
if (offsetTop <= this.offsetTop) {
this.setFixedForInstance()
}
const isArrivalDefault = (this.defaultInstancePosition - this.offsetTop) >= windowScrollTop
if (isArrivalDefault && this.affixStyle.position === 'fixed') {
this.affixStyle = {}
}
}
},
beforeDestroy () {
document.removeEventListener('scroll', this.scrollListener)
}
}
</script>
<style lang="scss" scoped>
.scroll-affix-container {
position: initial;
top: initial;
}
</style>