feat(scrollbar): support custom container & content

This commit is contained in:
07akioni 2019-12-26 23:59:23 +08:00
parent c04c51cffd
commit 3579187872

View File

@ -13,6 +13,7 @@
@dragstart.capture="handleDragStart" @dragstart.capture="handleDragStart"
> >
<div <div
v-if="!container"
ref="scrollContainer" ref="scrollContainer"
class="n-scrollbar-container" class="n-scrollbar-container"
@scroll="handleScroll" @scroll="handleScroll"
@ -24,6 +25,9 @@
<slot /> <slot />
</div> </div>
</div> </div>
<template v-else>
<slot />
</template>
<div <div
ref="verticalRail" ref="verticalRail"
class="n-scrollbar-rail n-scrollbar-rail--vertical" class="n-scrollbar-rail n-scrollbar-rail--vertical"
@ -89,6 +93,14 @@ export default {
withoutScrollbar: { withoutScrollbar: {
type: Boolean, type: Boolean,
default: false default: false
},
container: {
type: Function,
default: null
},
content: {
type: Function,
default: null
} }
}, },
data () { data () {
@ -179,7 +191,7 @@ export default {
// console.log('[NScrollbar.updated]') // console.log('[NScrollbar.updated]')
}, },
beforeDestroy () { beforeDestroy () {
resizeObserverDelagate.unregisterHandler(this.$refs.scrollContent) resizeObserverDelagate.unregisterHandler(this._content())
}, },
destroyed () { destroyed () {
window.clearTimeout(this.horizontalScrollbarVanishTimerId) window.clearTimeout(this.horizontalScrollbarVanishTimerId)
@ -189,9 +201,27 @@ export default {
}, },
mounted () { mounted () {
this.updateParameters() this.updateParameters()
resizeObserverDelagate.registerHandler(this.$refs.scrollContent, this.updateParameters) this.$nextTick().then(() => {
if (this.container) {
const containerEl = this.container()
containerEl.addEventListener('scroll', this.handleScroll)
}
})
resizeObserverDelagate.registerHandler(this._content(), this.updateParameters)
}, },
methods: { methods: {
_container () {
if (this.container) {
return this.container()
}
return this.$refs.scrollContainer
},
_content () {
if (this.content) {
return this.content()
}
return this.$refs.scrollContent
},
disableScrollbar () { disableScrollbar () {
this.hideScrollbar() this.hideScrollbar()
this.disabled = true this.disabled = true
@ -206,30 +236,30 @@ export default {
this.showVeriticalScrollbar = true this.showVeriticalScrollbar = true
}, },
scrollToTop (smooth = false) { scrollToTop (smooth = false) {
if (this.$refs.scrollContainer) { if (this._container()) {
this.$refs.scrollContainer.scrollTo({ this._container().scrollTo({
top: 0 top: 0
}) })
} }
}, },
scrollToBottom (smooth = false) { scrollToBottom (smooth = false) {
if (this.$refs.scrollContainer) { if (this._container()) {
this.$refs.scrollContainer.scrollTo({ this._container().scrollTo({
top: this.$refs.scrollContent.offsetHeight top: this._content().offsetHeight
}) })
} }
}, },
scrollToElement (el) { scrollToElement (el) {
if (this.withoutScrollbar) return if (this.withoutScrollbar) return
if (el.offsetTop < this.$refs.scrollContainer.scrollTop) { if (el.offsetTop < this._container().scrollTop) {
this.$refs.scrollContainer.scrollTo({ this._container().scrollTo({
top: el.offsetTop, top: el.offsetTop,
left: 0, left: 0,
behavior: 'smooth' behavior: 'smooth'
}) })
} else if (el.offsetTop + el.offsetHeight > this.$refs.scrollContainer.scrollTop + this.$refs.scrollContainer.offsetHeight) { } else if (el.offsetTop + el.offsetHeight > this._container().scrollTop + this._container().offsetHeight) {
this.$refs.scrollContainer.scrollTo({ this._container().scrollTo({
top: el.offsetTop + el.offsetHeight - this.$refs.scrollContainer.offsetHeight, top: el.offsetTop + el.offsetHeight - this._container().offsetHeight,
left: 0, left: 0,
behavior: 'smooth' behavior: 'smooth'
}) })
@ -285,26 +315,26 @@ export default {
}, },
handleScroll (e) { handleScroll (e) {
if (this.disabled) return if (this.disabled) return
this.$emit('scroll', e, this.$refs.scrollContainer, this.$refs.scrollContent) this.$emit('scroll', e, this._container(), this._content())
this.updateScrollParameters() this.updateScrollParameters()
}, },
updateScrollParameters () { updateScrollParameters () {
if (this.$refs.scrollContainer) { if (this._container()) {
this.containerScrollTop = this.$refs.scrollContainer.scrollTop this.containerScrollTop = this._container().scrollTop
this.containerScrollLeft = this.$refs.scrollContainer.scrollLeft this.containerScrollLeft = this._container().scrollLeft
} }
}, },
updatePositionParameters () { updatePositionParameters () {
/** /**
* Don't use getClientBoundingRect because element may be scale transformed * Don't use getClientBoundingRect because element may be scale transformed
*/ */
if (this.$refs.scrollContent) { if (this._content()) {
this.contentHeight = this.$refs.scrollContent.offsetHeight this.contentHeight = this._content().offsetHeight
this.contentWidth = this.$refs.scrollContent.offsetWidth this.contentWidth = this._content().offsetWidth
} }
if (this.$refs.scrollContainer) { if (this._container()) {
this.containerHeight = this.$refs.scrollContainer.offsetHeight this.containerHeight = this._container().offsetHeight
this.containerWidth = this.$refs.scrollContainer.offsetWidth this.containerWidth = this._container().offsetWidth
} }
if (this.$refs.horizontalRail) { if (this.$refs.horizontalRail) {
this.horizontalRailWidth = this.$refs.horizontalRail.offsetWidth this.horizontalRailWidth = this.$refs.horizontalRail.offsetWidth
@ -335,7 +365,7 @@ export default {
let toScrollLeft = this.memorizedHorizontalLeft + dScrollLeft let toScrollLeft = this.memorizedHorizontalLeft + dScrollLeft
toScrollLeft = Math.min(toScrollLeftUpperBound, toScrollLeft) toScrollLeft = Math.min(toScrollLeftUpperBound, toScrollLeft)
toScrollLeft = Math.max(toScrollLeft, 0) toScrollLeft = Math.max(toScrollLeft, 0)
this.$refs.scrollContainer.scrollLeft = toScrollLeft this._container().scrollLeft = toScrollLeft
} }
}, },
handleHorizontalScrollMouseUp (e) { handleHorizontalScrollMouseUp (e) {
@ -366,7 +396,7 @@ export default {
let toScrollTop = this.memorizedVerticalTop + dScrollTop let toScrollTop = this.memorizedVerticalTop + dScrollTop
toScrollTop = Math.min(toScrollTopUpperBound, toScrollTop) toScrollTop = Math.min(toScrollTopUpperBound, toScrollTop)
toScrollTop = Math.max(toScrollTop, 0) toScrollTop = Math.max(toScrollTop, 0)
this.$refs.scrollContainer.scrollTop = toScrollTop this._container().scrollTop = toScrollTop
} }
}, },
handleVerticalScrollMouseUp (e) { handleVerticalScrollMouseUp (e) {