@fesjs/fes-design
Version:
fes-design for PC
212 lines (206 loc) • 7.29 kB
JavaScript
import { defineComponent, ref, computed, onMounted, watch, onBeforeUnmount, resolveComponent, openBlock, createElementBlock, normalizeClass, createElementVNode, normalizeStyle, renderSlot, Fragment, createVNode, createCommentVNode } from 'vue';
import getPrefixCls from '../_util/getPrefixCls';
import { useTheme } from '../_theme/useTheme';
import { pxfy, requestAnimationFrame } from '../_util/utils';
import useResize from '../_util/use/useResize';
import FBar from './bar.js';
import useScrollbar from './useScrollbar';
import { scrollbarProps } from './const';
const prefixCls = getPrefixCls('scrollbar');
var script = defineComponent({
name: 'FScrollbar',
components: {
FBar
},
props: scrollbarProps,
emits: ['scroll'],
setup(props, _ref) {
let {
emit
} = _ref;
useTheme();
const {
onUpdate,
onScroll,
containerRef,
ratioX,
ratioY,
thumbMoveX,
thumbMoveY,
sizeHeight,
sizeWidth,
scrollX,
scrollXRatio,
scrollY,
scrollYRatio
} = useScrollbar(props);
const scrollbarRef = ref();
const contentRef = ref();
const shadowRef = computed(() => {
if (typeof props.shadow === 'boolean') {
return {
x: props.shadow,
y: props.shadow
};
}
return props.shadow;
});
const style = computed(() => [props.containerStyle, {
height: pxfy(props.height),
maxHeight: pxfy(props.maxHeight)
}]);
const wrapperClassRef = computed(() => [prefixCls]);
const containerClassRef = computed(() => [`${prefixCls}-container`, props.containerClass, !props.native && `${prefixCls}-hidden-native-bar`]);
const handleScroll = event => {
onScroll();
const containerRefValue = containerRef.value;
if (containerRefValue) {
emit('scroll', event, containerRefValue);
}
};
// contentRef 为 containerRef 的子元素,所以 containerRef 不需要再监听
useResize(contentRef, () => {
onUpdate();
onScroll();
}, computed(() => props.noresize), false);
useResize(scrollbarRef, () => {
onUpdate();
onScroll();
}, computed(() => props.noresize), false);
onMounted(() => {
// 等待content插槽内容渲染完毕用setTimeout
if (!props.native) {
setTimeout(onUpdate, 0);
}
setTimeout(onScroll, 0);
});
watch(() => props.minSize, () => {
onUpdate();
onScroll();
}, {
immediate: false
});
let rafId;
const move = (type, to, duration) => {
if (!duration || duration <= 0) {
containerRef.value[type] = to;
return;
}
const difference = to - containerRef.value[type];
const perTick = difference / duration * 10;
rafId = requestAnimationFrame(() => {
containerRef.value[type] += perTick;
if (containerRef.value[type] === to) {
return;
}
move(type, to, duration - 10);
});
};
const setScrollTop = (val, duration) => {
move('scrollTop', val, duration);
};
const setScrollLeft = (val, duration) => {
move('scrollLeft', val, duration);
};
const scrollToEnd = (direction, duration) => {
if (direction === 'bottom') {
move('scrollTop', contentRef.value.offsetHeight, duration);
} else if (direction === 'right') {
move('scrollLeft', contentRef.value.offsetWidth, duration);
} else {
move('scrollTop', contentRef.value.offsetHeight, duration);
move('scrollLeft', contentRef.value.offsetWidth, duration);
}
};
onBeforeUnmount(() => {
if (rafId) {
cancelAnimationFrame(rafId);
}
});
return {
scrollbarRef,
containerRef,
contentRef,
style,
prefixCls,
setScrollTop,
setScrollLeft,
scrollToEnd,
update: onUpdate,
handleScroll,
thumbMoveX,
thumbMoveY,
ratioX,
ratioY,
sizeHeight,
sizeWidth,
wrapperClassRef,
containerClassRef,
scrollX,
scrollXRatio,
scrollY,
scrollYRatio,
shadowRef
};
}
});
function render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_FBar = resolveComponent("FBar");
return openBlock(), createElementBlock("div", {
ref: "scrollbarRef",
class: normalizeClass(_ctx.wrapperClassRef)
}, [createElementVNode("div", {
ref: "containerRef",
class: normalizeClass(_ctx.containerClassRef),
style: normalizeStyle(_ctx.style),
onScroll: _cache[0] || (_cache[0] = function () {
return _ctx.handleScroll && _ctx.handleScroll(...arguments);
})
}, [createElementVNode("div", {
ref: "contentRef",
class: normalizeClass(`${_ctx.prefixCls}-content`),
style: normalizeStyle([_ctx.scrollX && {
width: 'fit-content'
}, _ctx.contentStyle])
}, [renderSlot(_ctx.$slots, "default")], 6 /* CLASS, STYLE */)], 38 /* CLASS, STYLE, NEED_HYDRATION */), !_ctx.native ? (openBlock(), createElementBlock(Fragment, {
key: 0
}, [createVNode(_component_FBar, {
thumbStyle: _ctx.thumbStyle,
scrollbarRef: [_ctx.scrollbarRef],
containerRef: _ctx.containerRef,
move: _ctx.thumbMoveX,
ratio: _ctx.ratioX,
size: _ctx.sizeWidth,
always: _ctx.always,
style: normalizeStyle(_ctx.horizontalRatioStyle)
}, null, 8 /* PROPS */, ["thumbStyle", "scrollbarRef", "containerRef", "move", "ratio", "size", "always", "style"]), createVNode(_component_FBar, {
thumbStyle: _ctx.thumbStyle,
scrollbarRef: [_ctx.scrollbarRef],
containerRef: _ctx.containerRef,
move: _ctx.thumbMoveY,
ratio: _ctx.ratioY,
size: _ctx.sizeHeight,
vertical: "",
always: _ctx.always,
style: normalizeStyle(_ctx.verticalRatioStyle)
}, null, 8 /* PROPS */, ["thumbStyle", "scrollbarRef", "containerRef", "move", "ratio", "size", "always", "style"])], 64 /* STABLE_FRAGMENT */)) : createCommentVNode("v-if", true), _ctx.shadowRef.x && _ctx.scrollX && _ctx.scrollXRatio < 1 ? (openBlock(), createElementBlock("div", {
key: 1,
class: normalizeClass(`${_ctx.prefixCls}-shadow-right`),
style: normalizeStyle(_ctx.shadowStyle)
}, null, 6 /* CLASS, STYLE */)) : createCommentVNode("v-if", true), _ctx.shadowRef.x && _ctx.scrollX && _ctx.scrollXRatio > 0 ? (openBlock(), createElementBlock("div", {
key: 2,
class: normalizeClass(`${_ctx.prefixCls}-shadow-left`),
style: normalizeStyle(_ctx.shadowStyle)
}, null, 6 /* CLASS, STYLE */)) : createCommentVNode("v-if", true), _ctx.shadowRef.y && _ctx.scrollY && _ctx.scrollYRatio < 1 ? (openBlock(), createElementBlock("div", {
key: 3,
class: normalizeClass(`${_ctx.prefixCls}-shadow-bottom`),
style: normalizeStyle(_ctx.shadowStyle)
}, null, 6 /* CLASS, STYLE */)) : createCommentVNode("v-if", true), _ctx.shadowRef.y && _ctx.scrollY && _ctx.scrollYRatio > 0 ? (openBlock(), createElementBlock("div", {
key: 4,
class: normalizeClass(`${_ctx.prefixCls}-shadow-top`),
style: normalizeStyle(_ctx.shadowStyle)
}, null, 6 /* CLASS, STYLE */)) : createCommentVNode("v-if", true)], 2 /* CLASS */);
}
script.render = render;
script.__file = "components/scrollbar/scrollbar.vue";
export { script as default };