跳转到内容

安装

React 18 或 19,以及浏览器环境。发布的 JavaScript 以 ES2020 为目标,依赖 <dialog>.showModal()、Pointer Events 和 ResizeObserver,因此下限是 Chrome 80、Firefox 98、Safari 15.4。引入预设样式表会把下限抬到 Chrome 111、 Firefox 113、Safari 16.2 —— 工具栏的表面色用了 CSS color-mix()。 从 react-img-view/primitives 自行组合界面,则仍适用较低的那条线。

服务端渲染没有问题:在预览器真正挂载之前,不会执行任何东西。 详见下面的服务端渲染与 Next.js

React 部分的入口都带 "use client" 发布,所以直接在 Server Component 树里引入就够了 —— Next.js 会把这次引入当作 client 边界,你不需要再自己 包一层。

渲染过程中不会碰到 document。portal 的目标(container,默认 document.body)只在预览器挂载并打开之后才读取,因此服务端渲染根本不会 输出 dialog 的任何标记。

需要你主动做决定的只有文案。Group 回退到固定的英文默认值,而不是去读 navigator.language,这样服务端输出和 hydration 结果永远一致。要换语言就 显式传入,而且传的值在两端必须相同:

import { ImageView } from 'react-img-view'
import zhCN from 'react-img-view/locales/zh-CN'
import 'react-img-view/styles.css'
export default function Gallery({ images }: { images: { src: string; name: string }[] }) {
return <ImageView.Group images={images} labels={zhCN} />
}

如果 labels 取自只有浏览器才知道的东西 —— 浏览器语言、localStorage 里的值 —— 两端渲染出的文字就会不一样,React 会报 hydration 警告。请改为 从请求里取:一个 cookie,或者路由里的语言段。

Terminal window
npm install react-img-view
Terminal window
pnpm add react-img-view

这个包没有自己的运行时依赖 —— 手势引擎、动画驱动和弹窗都只依赖 React 和 DOM。

primitives 入口不带预设;主入口提供默认组合,样式表负责它的外观。一共有三条路可选。

import 'react-img-view/styles.css'

所有取值都来自 CSS 自定义属性,设置在 :root 和 dialog 元素本身上 —— 不要设置在某个祖先类上:预览器会 portal 到 DOM 树外面,作用域限定在包裹类上的 规则跟不过去。

:root {
--riv-accent: #0f766e;
--riv-chrome: #ffffff;
--riv-stage: #f4f4f5;
}

深色模式会自动跟随 prefers-color-scheme;如果要强制固定,在 :root 或 dialog 上加 data-riv-theme="light"data-riv-theme="dark"。完整的属性清单见 自定义

如果项目已经在用 Tailwind 和 shadcn 那套约定,可以直接装 Tailwind 类名版本 —— 它会把真实源码放进你的仓库,和其它组件一样可以随意修改:

Terminal window
npx shadcn add https://baron04.github.io/react-img-view/r/image-view.json

它和 CSS 预设是同一套设计的两种分发方式:预设用 CSS 自定义属性, 区块用 Tailwind 工具类。复制进项目的只有呈现层;行为(手势、弹窗、 键盘、开关动画)仍然是对 react-img-view 的真实依赖——和 shadcn 自己的区块对 Radix 的拆分方式一致。

所有部件都暴露稳定的 data-* 钩子;控件和布局区域支持 asChildImageView 则始终 直接复用唯一的子元素。因此你可以从零开始写样式:用属性选择器、Tailwind 的 data-[active]:… 变体,或你自己设计系统里的组件。见自定义