docs(components): [scrollbar] (#10564)

* docs(components): [scrollbar]
This commit is contained in:
Xc
2022-11-13 19:51:13 +08:00
committed by GitHub
parent 90f7a484e7
commit cb490ae3c1
5 changed files with 124 additions and 75 deletions

View File

@@ -39,39 +39,43 @@ scrollbar/manual-scroll
:::
## Scrollbar Attributes
## API
| Name | Description | Type | Accepted Values | Default |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------- | --------------- | ------- |
| height | height of scrollbar | string / number | — | — |
| max-height | max height of scrollbar | string / number | — | — |
| native | whether to use the native scrollbar style | boolean | — | false |
| wrap-style | style of warp container | string | — | — |
| wrap-class | class of warp container | string | — | — |
| view-style | style of view | string | — | — |
| view-class | class of view | string | — | — |
| noresize | do not respond to container size changes, if the container size does not change, it is better to set it to optimize performance | boolean | — | false |
| tag | element tag of the view | string | — | div |
| always | always show scrollbar | boolean | — | false |
| min-size | minimum size of scrollbar | number | — | 20 |
### Attributes
## Scrollbar Events
| Name | Description | Type | Default |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | ------- |
| height | height of scrollbar | ^[string] \| ^[number] | — |
| max-height | max height of scrollbar | ^[string] \| ^[number] | — |
| native | whether to use the native scrollbar style | ^[boolean] | false |
| wrap-style | style of wrap container | ^[string] \| ^[object]`CSSProperties \| CSSProperties[] \| string[]` | — |
| wrap-class | class of wrap container | ^[string] | — |
| view-style | style of view | ^[string] \| ^[object]`CSSProperties \| CSSProperties[] \| string[]` | — |
| view-class | class of view | ^[string] | — |
| noresize | do not respond to container size changes, if the container size does not change, it is better to set it to optimize performance | ^[boolean] | false |
| tag | element tag of the view | ^[string] | div |
| always | always show scrollbar | ^[boolean] | false |
| min-size | minimum size of scrollbar | ^[number] | 20 |
| Name | Description | Parameters |
| ------ | ----------------------- | ------------------------------------------------- |
| scroll | triggers when scrolling | distance of scrolling `{ scrollLeft, scrollTop }` |
### Events
## Scrollbar Methods
| Name | Description | Type |
| ------ | ----------------------------------------------------- | ---------------------------------------------------------------- |
| scroll | triggers when scrolling, return distance of scrolling | ^[Function]`({ scrollLeft: number, scrollTop: number }) => void` |
| Method | Description | Parameters |
| ------------- | ------------------------------------------ | ----------------------------------------------------- |
| scrollTo | scrolls to a particular set of coordinates | (options: ScrollToOptions \| number, yCoord?: number) |
| setScrollTop | Set distance to scroll top | (scrollTop: number) |
| setScrollLeft | Set distance to scroll left | (scrollLeft: number) |
| update | update scrollbar state manually | — |
### Slots
## Scrollbar Slots
| Name | Description |
| ------- | ------------------------- |
| default | customize default content |
| Name | Description |
| ---- | ------------------------- |
| — | customize default content |
### Exposes
| Method | Description | Type |
| ------------- | ------------------------------------------ | -------------------------------------------------------------------------- |
| handleScroll | handle scroll event | ^[Function]`() => void` |
| scrollTo | scrolls to a particular set of coordinates | ^[Function]`(options: ScrollToOptions \| number, yCoord?: number) => void` |
| setScrollTop | Set distance to scroll top | ^[Function]`(scrollTop: number) => void` |
| setScrollLeft | Set distance to scroll left | ^[Function]`(scrollLeft: number) => void` |
| update | update scrollbar state manually | ^[Function]`() => void` |
| wrapRef | scrollbar wrap ref | ^[Object]`Ref<HTMLDivElement>` |

View File

@@ -3,37 +3,73 @@ import type { ExtractPropTypes, StyleValue } from 'vue'
import type Scrollbar from './scrollbar.vue'
export const scrollbarProps = buildProps({
/**
* @description height of scrollbar
*/
height: {
type: [String, Number],
default: '',
},
/**
* @description max height of scrollbar
*/
maxHeight: {
type: [String, Number],
default: '',
},
native: Boolean,
/**
* @description whether to use the native scrollbar
*/
native: {
type: Boolean,
default: false,
},
/**
* @description style of wrap
*/
wrapStyle: {
type: definePropType<StyleValue>([String, Object, Array]),
default: '',
},
/**
* @description class of wrap
*/
wrapClass: {
type: [String, Array],
default: '',
},
/**
* @description class of view
*/
viewClass: {
type: [String, Array],
default: '',
},
/**
* @description style of view
*/
viewStyle: {
type: [String, Array, Object],
default: '',
},
/**
* @description do not respond to container size changes, if the container size does not change, it is better to set it to optimize performance
*/
noresize: Boolean, // 如果 container 尺寸不会发生变化,最好设置它可以优化性能
/**
* @description element tag of the view
*/
tag: {
type: String,
default: 'div',
},
/**
* @description always show
*/
always: Boolean,
/**
* @description minimum size of scrollbar
*/
minSize: {
type: Number,
default: 20,

View File

@@ -1,19 +1,10 @@
<template>
<div ref="scrollbar$" :class="ns.b()">
<div
ref="wrap$"
:class="[
wrapClass,
ns.e('wrap'),
{ [ns.em('wrap', 'hidden-default')]: !native },
]"
:style="style"
@scroll="handleScroll"
>
<div ref="scrollbarRef" :class="ns.b()">
<div ref="wrapRef" :class="wrapKls" :style="style" @scroll="handleScroll">
<component
:is="tag"
ref="resize$"
:class="[ns.e('view'), viewClass]"
ref="resizeRef"
:class="resizeKls"
:style="viewStyle"
>
<slot />
@@ -52,8 +43,10 @@ import { scrollbarEmits, scrollbarProps } from './scrollbar'
import type { BarInstance } from './bar'
import type { CSSProperties, StyleValue } from 'vue'
const COMPONENT_NAME = 'ElScrollbar'
defineOptions({
name: 'ElScrollbar',
name: COMPONENT_NAME,
})
const props = defineProps(scrollbarProps)
@@ -64,16 +57,15 @@ const ns = useNamespace('scrollbar')
let stopResizeObserver: (() => void) | undefined = undefined
let stopResizeListener: (() => void) | undefined = undefined
const scrollbar$ = ref<HTMLDivElement>()
const wrap$ = ref<HTMLDivElement>()
const resize$ = ref<HTMLElement>()
const scrollbarRef = ref<HTMLDivElement>()
const wrapRef = ref<HTMLDivElement>()
const resizeRef = ref<HTMLElement>()
const sizeWidth = ref('0')
const sizeHeight = ref('0')
const barRef = ref<BarInstance>()
const ratioY = ref(1)
const ratioX = ref(1)
const SCOPE = 'ElScrollbar'
const style = computed<StyleValue>(() => {
const style: CSSProperties = {}
@@ -82,13 +74,25 @@ const style = computed<StyleValue>(() => {
return [props.wrapStyle, style]
})
const wrapKls = computed(() => {
return [
props.wrapClass,
ns.e('wrap'),
{ [ns.em('wrap', 'hidden-default')]: !props.native },
]
})
const resizeKls = computed(() => {
return [ns.e('view'), props.viewClass]
})
const handleScroll = () => {
if (wrap$.value) {
barRef.value?.handleScroll(wrap$.value)
if (wrapRef.value) {
barRef.value?.handleScroll(wrapRef.value)
emit('scroll', {
scrollTop: wrap$.value.scrollTop,
scrollLeft: wrap$.value.scrollLeft,
scrollTop: wrapRef.value.scrollTop,
scrollLeft: wrapRef.value.scrollLeft,
})
}
}
@@ -99,35 +103,35 @@ function scrollTo(xCord: number, yCord?: number): void
function scrollTo(options: ScrollToOptions): void
function scrollTo(arg1: unknown, arg2?: number) {
if (isObject(arg1)) {
wrap$.value!.scrollTo(arg1)
wrapRef.value!.scrollTo(arg1)
} else if (isNumber(arg1) && isNumber(arg2)) {
wrap$.value!.scrollTo(arg1, arg2)
wrapRef.value!.scrollTo(arg1, arg2)
}
}
const setScrollTop = (value: number) => {
if (!isNumber(value)) {
debugWarn(SCOPE, 'value must be a number')
debugWarn(COMPONENT_NAME, 'value must be a number')
return
}
wrap$.value!.scrollTop = value
wrapRef.value!.scrollTop = value
}
const setScrollLeft = (value: number) => {
if (!isNumber(value)) {
debugWarn(SCOPE, 'value must be a number')
debugWarn(COMPONENT_NAME, 'value must be a number')
return
}
wrap$.value!.scrollLeft = value
wrapRef.value!.scrollLeft = value
}
const update = () => {
if (!wrap$.value) return
const offsetHeight = wrap$.value.offsetHeight - GAP
const offsetWidth = wrap$.value.offsetWidth - GAP
if (!wrapRef.value) return
const offsetHeight = wrapRef.value.offsetHeight - GAP
const offsetWidth = wrapRef.value.offsetWidth - GAP
const originalHeight = offsetHeight ** 2 / wrap$.value.scrollHeight
const originalWidth = offsetWidth ** 2 / wrap$.value.scrollWidth
const originalHeight = offsetHeight ** 2 / wrapRef.value.scrollHeight
const originalWidth = offsetWidth ** 2 / wrapRef.value.scrollWidth
const height = Math.max(originalHeight, props.minSize)
const width = Math.max(originalWidth, props.minSize)
@@ -151,7 +155,7 @@ watch(
stopResizeObserver?.()
stopResizeListener?.()
} else {
;({ stop: stopResizeObserver } = useResizeObserver(resize$, update))
;({ stop: stopResizeObserver } = useResizeObserver(resizeRef, update))
stopResizeListener = useEventListener('resize', update)
}
},
@@ -164,8 +168,8 @@ watch(
if (!props.native)
nextTick(() => {
update()
if (wrap$.value) {
barRef.value?.handleScroll(wrap$.value)
if (wrapRef.value) {
barRef.value?.handleScroll(wrapRef.value)
}
})
}
@@ -174,8 +178,8 @@ watch(
provide(
scrollbarContextKey,
reactive({
scrollbarElement: scrollbar$,
wrapElement: wrap$,
scrollbarElement: scrollbarRef,
wrapElement: wrapRef,
})
)
@@ -189,7 +193,7 @@ onUpdated(() => update())
defineExpose({
/** @description scrollbar wrap ref */
wrap$,
wrapRef,
/** @description update scrollbar state manually */
update,
/** @description scrolls to a particular set of coordinates */

View File

@@ -71,7 +71,7 @@ class TableLayout<T> {
let scrollY = true
const prevScrollY = this.scrollY.value
scrollY =
scrollBarRef.wrap$.scrollHeight > scrollBarRef.wrap$.clientHeight
scrollBarRef.wrapRef.scrollHeight > scrollBarRef.wrapRef.clientHeight
this.scrollY.value = scrollY
return prevScrollY !== scrollY
}

View File

@@ -172,7 +172,7 @@ function useStyle<T>(
}
return
}
const scrollContainer = table.refs.scrollBarRef.wrap$
const scrollContainer = table.refs.scrollBarRef.wrapRef
if (!scrollContainer) return
const { scrollLeft, offsetWidth, scrollWidth } = scrollContainer
const { headerWrapper, footerWrapper } = table.refs
@@ -190,10 +190,15 @@ function useStyle<T>(
const bindEvents = () => {
if (!table.refs.scrollBarRef) return
if (table.refs.scrollBarRef.wrap$) {
useEventListener(table.refs.scrollBarRef.wrap$, 'scroll', syncPosition, {
passive: true,
})
if (table.refs.scrollBarRef.wrapRef) {
useEventListener(
table.refs.scrollBarRef.wrapRef,
'scroll',
syncPosition,
{
passive: true,
}
)
}
if (props.fit) {
useResizeObserver(table.vnode.el as HTMLElement, resizeListener)