v0.1.9

Affix 固钉

引入import { Affix } from '@apollo-design/ui';

滚动到指定偏移后,将内容固定到窗口或实际滚动容器的可视边缘。默认插槽承载完整 Vue 内容。

<Affix :offset-top="16" :target="() => scrollArea" @change="onAffixed">
  <button>固定工具栏</button>
</Affix>

API

Prop 说明 类型 默认值
offsetTop 顶部固钉偏移 number 两种偏移都未传时为 0
offsetBottom 底部固钉偏移;两个条件同时命中时顶部优先,顶部未命中时仍可命中底部 number —
target 返回实际滚动元素或 Window;未传依次使用 Provider.getTargetContainer、window () => HTMLElement | Window | null | undefined —
prefixCls 当前组件类名前缀 string apollo-affix

target 返回 null/undefined 表示尚未就绪,释放旧目标监听并撤除固钉状态,不退回 window。响应式 ref 就绪或替换后自动同步;非响应式目标变化可调用已有 updatePosition() 重新读取。

事件 载荷 时机
change affixed: boolean 实际固钉状态翻转时;同一状态的滚动不重复通知
插槽 说明
default 固钉内容,保留完整 VNodeChild 和节点身份
AffixRef 说明
updatePosition(): void 合并到下一帧重新测量当前目标和内容

没有新增实例方法。模板 ref 可声明为 ref<AffixRef | null>(null)。

原生属性与当前配置

根是外层占位测量 div,原生 class/style、id、data、ARIA 和监听器只落此处。class/style 使用 Vue 的字符串、数组和对象合并,调用者样式覆盖 ConfigProvider.components.affix.style;这些字段不另声明成组件 Props。固钉层与占位层是内部定位节点。

getPrefixCls、组件配置和主题读取当前 Provider。唯一组件 Token 是 zIndexPopup,默认由 zIndexBase + 10 派生;替换、撤除和显式 0 均作用于实际固钉层。

<ConfigProvider :theme="{ components: { Affix: { zIndexPopup: 20 } } }">
  <Affix :offset-top="0">工具栏</Affix>
</ConfigProvider>

几何与资源

保留顶部/底部的亚像素比较与外层布局测量基准。顶部条件优先于底部条件,并非删除另一个条件。固定宽度跟随外层可用宽度;内容保留自然高度,其真实尺寸通过已有 ResizeObserver 同步占位,支持增长和缩小,不重挂内部输入。

只在挂载后测量和绑定。监听当前目标、影响目标或占位层位置的滚动祖先及目标所属窗口的滚动;外页或嵌套祖先滚动移动目标后,顶部和底部固钉都按当前位置更新。滚动事件保持逐帧合并与同位置快路径;内容/容器的尺寸通知走完整测量。换目标、目标变为空和卸载释放这些监听、观察及待执行帧,SSR 不调度这些副作用。没有为无尺寸/滚动/显式更新信号的任意位置重排增加观察或轮询。

代码演示

实时示例

基础 #

最简单的用法:滚动到 offsetTop 之后,按钮固钉在顶部。

固钉时组件会渲染一个等高占位层(aria-hidden),避免页面布局跳动; 且只有此时内层才有 apollo-affix 类名(position: fixed)。

实时示例

固定在底部 #

offsetBottom 与 offsetTop 互斥:两者都传时只有 offsetTop 生效 (antd 的 internalOffsetTop 互锁推导,见 docs/analysis/affix.md §3)。

实时示例

固钉状态改变回调 #

@change 只在状态翻转时触发(连续固钉不会重复发)。 Vue 侧是 emit('change', affixed),模板上写 @change —— antd 的 onChange prop 不移植成 prop(规则 C19)。

实时示例

滚动容器 #

target 是一个返回元素或 window 的函数(不是元素本身)。 换绑 target 时,旧 target 上的监听也会被解绑。

⚠️ 固定在容器底部时,偏移量是「容器可视区底边到视口底边的距离」参与计算 (getFixedBottom 用 window.innerHeight,不是容器高度)。

实时示例

手动更新位置 #

ref 只暴露 updatePosition(与 antd 的 useImperativeHandle 一致): 内容尺寸或布局在程序里变化后,手动触发一次重新测量。

尺寸变化通常由内部的 ResizeObserver 自动捕捉,无需手动调用。

basic、offset-bottom、on-change、target、update-position;原有几何与 s54 监听幂等回归保留。统一九维与发布验收另行执行。

Powered by Vue 3 + ViteApollo Design · Vue NativeGitHub