feat(ssr): 真 SSR 收尾——干净 hydration 与浏览器原生滚动恢复
- 修复 onRenderClient 引入 serverClient 导致浏览器 process is not defined: 抽出双端安全的 ssr/feedSeed.ts 作为唯一数据播种入口,serverClient 加 SSR 守卫 - 修复 React 19 Fizz Suspense Outlining:Suspense 边界从布局 Outlet 下移到 各懒加载路由,SSR 输出不再出现 <!--$?--> / $RB / template 探针标记 - 修复窄屏 React #418 hydration 致命错误:useMediaQuery 首帧恒 false, useLayoutEffect 绘制前同步真实值;主题改 cookie 存储供 SSR 直出, head 内联防闪烁/缩放脚本移除(缩放锁改为客户端 zoomGuard 模块) - 清理假 SSR 残留:删除 StaticFeedList 镜像组件、SSR 图标生成脚本、 探针与死代码;列表接口裁剪正文,仅下发 excerpt/first_image - Feed 与帖子详情改为窗口滚动(app-shell--doc-scroll):删除虚拟列表、 自研滚动快照与全局滚轮 hack;F5/前进后退滚动位置全部交给浏览器原生 历史恢复,HTML 响应头 no-cache 配合;锚点/楼层用 scrollIntoView + scroll-margin-top 适配 sticky 顶栏
This commit is contained in:
33
frontend/src/utils/zoomGuard.ts
Normal file
33
frontend/src/utils/zoomGuard.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 手机/平板双指与手势缩放锁(头像裁剪、图片灯箱区域放行 pinch)。
|
||||
*
|
||||
* 只监听用户手势事件,而手势必然发生在页面加载与客户端 bundle 执行之后,
|
||||
* 因此无需像主题脚本那样内联在 <head> 中,在客户端入口安装即可。
|
||||
*/
|
||||
export function installZoomGuard(): void {
|
||||
if (typeof document === 'undefined') return;
|
||||
|
||||
const inZoomAllowArea = (target: EventTarget | null): boolean =>
|
||||
!!target
|
||||
&& target instanceof Element
|
||||
&& typeof target.closest === 'function'
|
||||
&& !!target.closest('.avatar-crop-stage, .image-lightbox');
|
||||
|
||||
const blockGesture = (e: Event) => {
|
||||
if (inZoomAllowArea(e.target)) return;
|
||||
if (e.cancelable) e.preventDefault();
|
||||
};
|
||||
|
||||
const blockMultiTouch = (e: TouchEvent) => {
|
||||
if (e.touches && e.touches.length > 1) {
|
||||
if (inZoomAllowArea(e.target)) return;
|
||||
if (e.cancelable) e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('gesturestart', blockGesture, { passive: false });
|
||||
document.addEventListener('gesturechange', blockGesture, { passive: false });
|
||||
document.addEventListener('gestureend', blockGesture, { passive: false });
|
||||
document.addEventListener('touchstart', blockMultiTouch, { passive: false });
|
||||
document.addEventListener('touchmove', blockMultiTouch, { passive: false });
|
||||
}
|
||||
Reference in New Issue
Block a user