UNPKG

tdesign-mobile-vue

Version:
1 lines 6.57 kB
{"version":3,"file":"sticky.mjs","sources":["../../src/sticky/sticky.tsx"],"sourcesContent":["import { computed, defineComponent, ref, watch } from 'vue';\nimport { useElementBounding } from '@vueuse/core';\nimport StickyProps from './props';\nimport config from '../config';\nimport { usePrefixClass } from '../hooks/useClass';\nimport { useTNodeJSX } from '../hooks/tnode';\nimport useElementRect from '../hooks/useElementRect';\n\nconst { prefix } = config;\n\nexport default defineComponent({\n name: `${prefix}-sticky`,\n props: StickyProps,\n setup(props) {\n const renderTNodeJSX = useTNodeJSX();\n const stickyBarClass = usePrefixClass('sticky');\n\n // box 用于占位和记录边界\n // content 用于实际定位\n const boxRef = ref<HTMLElement>();\n const { top: boxTop } = useElementBounding(boxRef);\n const contentRef = ref<HTMLElement>();\n const { top: contentTop, height } = useElementBounding(contentRef);\n\n const stickyStyle = computed(() => `height:${height.value}px;`);\n\n // 处理 container 的解析和边界计算。\n // 将 props.container 包装为 ref,以便正确监听 Vue ref 类型的 container\n const containerRef = computed(() => props.container);\n const {\n element: containerElement,\n rect: containerRect,\n updateElement: updateContainer,\n } = useElementRect(containerRef, { immediate: true });\n\n // 监听 boxTop 变化,在滚动时更新 container 边界信息\n watch(boxTop, () => {\n if (containerElement.value) {\n updateContainer();\n }\n });\n\n // 通过改变 content 的定位来实现 sticky 效果\n const contentStyles = computed(() => {\n let styleStr = `z-index:${props.zIndex};`;\n let isFixed = false;\n if (props.disabled) return styleStr;\n const offsetTop = Number(props.offsetTop);\n if (containerElement.value) {\n const { bottom: containerBottom } = containerRect.value;\n // sticky 固定的条件:到达吸附位置 且 container 在可视区域内\n const shouldFix = boxTop.value <= offsetTop && containerBottom > 0;\n\n if (shouldFix) {\n styleStr += `position:fixed;top:${offsetTop}px;`;\n isFixed = true;\n }\n\n // transform 的计算独立于 fixed 状态\n // 当 sticky 即将超出 container 底部时,使用 transform 让它跟随 container 一起移动\n const difference = containerBottom - offsetTop - height.value;\n if (difference < 0) {\n styleStr += `transform:translate3d(0, ${difference}px, 0);`;\n }\n } else if (boxTop.value <= offsetTop) {\n styleStr += `position:fixed;top:${offsetTop}px;`;\n isFixed = true;\n }\n props.onScroll?.({ scrollTop: contentTop.value, isFixed });\n return styleStr;\n });\n\n return () => (\n <div ref={boxRef} class={stickyBarClass.value} style={stickyStyle.value}>\n <div ref={contentRef} class={`${stickyBarClass.value}__content`} style={contentStyles.value}>\n {renderTNodeJSX('default')}\n </div>\n </div>\n );\n },\n});\n"],"names":["prefix","config","defineComponent","name","props","StickyProps","setup","renderTNodeJSX","useTNodeJSX","stickyBarClass","usePrefixClass","boxRef","ref","_useElementBounding","useElementBounding","boxTop","top","contentRef","_useElementBounding2","contentTop","height","stickyStyle","computed","concat","value","containerRef","container","_useElementRect","useElementRect","immediate","containerElement","element","containerRect","rect","updateContainer","updateElement","watch","contentStyles","_props$onScroll","styleStr","zIndex","isFixed","disabled","offsetTop","Number","containerBottom","bottom","shouldFix","difference","onScroll","call","scrollTop","_createVNode"],"mappings":"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"}