服务端渲染

所有 reelkit 包都能在服务端运行。可以在 Next.js、Remix、Angular Universal 或任何服务端渲染方案里直接引入和渲染。

工作原理

核心的滑动控制器是纯逻辑,构造时不碰 DOM。 手势监听、键盘事件和动画只会在客户端的生命周期钩子里挂载。

服务端渲染时, Reel 组件会渲染一个静态容器,里面是初始可见的幻灯片(通常是 3 张:上一张、当前、下一张)。水合之后,它会挂上手势、键盘和滚轮控制器, 让一切变得可交互。

包名服务端安全备注
@reelkit/core纯逻辑,导入和构造时都不使用浏览器 API
@reelkit/reactReel 和 ReelIndicator 在服务端渲染出合法的 HTML
@reelkit/angular独立组件,兼容 Angular Universal 的服务端渲染
@reelkit/vue组件与组合式函数,兼容 Nuxt 3 的服务端渲染
@reelkit/react-reel-player关闭时(isOpen=false)什么都不渲染
@reelkit/react-lightbox关闭时(isOpen=false)什么都不渲染
@reelkit/angular-reel-player关闭时(isOpen=false)什么都不渲染
@reelkit/angular-lightbox关闭时(isOpen=false)什么都不渲染
@reelkit/stories-core与框架无关,不访问 DOM
@reelkit/react-stories-player关闭时(isOpen=false)什么都不渲染

Next.js App Router

Reel 会用到浏览器事件和 ref,所以它是客户端组件。请在使用 Reel 的文件顶部加上 "use client" 指令:

tsx

数据可以在服务端组件里取好,再传下去:

tsx

Next.js Pages Router

Pages Router 不需要额外配置。组件会在服务端渲染,然后在客户端水合:

tsx

服务端渲染下的响应式尺寸

干脆不要传 size 属性。没有 size 时,Reel 会在客户端用 ResizeObserver 自动测量容器。服务端渲染阶段滑动器渲染成一个空容器; 水合之后马上测量并渲染幻灯片:

tsx
自动测量是怎么工作的

省略 size 时,容器的尺寸必须由 CSS 决定(父级的 flex / grid、显式的宽高,或者百分比)。 在第一次测量完成之前滑动器什么都不渲染, 之后会填满测到的尺寸,并自动响应后续的尺寸变化。

显式尺寸(手动方案)

想要像素级的控制,就显式传 size 属性。由于服务端渲染时拿不到 window.innerWidth,请给一个默认值,并在挂载后更新:

tsx
小提示

默认尺寸尽量选你最常见的视口(比如移动端优先)。 如果实际视口不一样,滑动器会在水合时立刻重新调整。

浮层组件

ReelPlayerOverlay LightboxOverlay isOpen={false} 时什么都不渲染,所以默认就是服务端安全的。 只有被打开时(通常来自客户端的用户交互)才会挂载它们的 portal:

tsx

Angular Universal / 服务端渲染

所有 Angular 组件都是服务端安全的。滑动控制器把浏览器 API 的访问推迟到 afterRenderEffect 里。浮层组件在 isOpen=false 时什么都不渲染,因此服务端渲染阶段不会产出任何标记。

typescript

Nuxt 3

ReelKit 的 Vue 组件在 Nuxt 3 里开箱即用。由于 Reel 会用到浏览器 API(触摸事件、ResizeObserver),请把它包在 <ClientOnly> 组件里,或者用 .client.vue 后缀:

vue

Feed 组件里照常使用 Reel:

vue

服务端渲染下的响应式尺寸

省略 size 属性即可启用自动测量。Reel 会自动撑满父级的 100%。服务端渲染阶段它渲染一个空容器;水合之后测量并渲染幻灯片:

vue

直接使用核心包

如果你直接用 @reelkit/core 做自定义框架集成,控制器可以在服务端创建。 attach() observe() 则只在客户端调用:

typescript

小结

开箱即用的部分
  • 在服务端导入任意 reelkit 包
  • 服务端渲染阶段渲染滑动器组件(产出合法的静态 HTML)
  • 在服务端创建控制器
  • 浮层组件在 isOpen=false 时的表现
需要留意的地方
  • 省略 size 以启用自动测量;如果要用基于视口的尺寸,请给一个默认值
  • 直接使用核心包时,不要在服务端调用 attach()/observe()