在 iframe 中使用 Chakra UI
Chakra UI 在 iframe 中的安装和使用指南
iframe 有助于在单独的上下文中隔离样式和逻辑。例如,你可能希望在专用沙盒中展示 Chakra 组件。
¥Iframes are useful for isolating styles and logic in a separate context. For example, you might want to showcase a Chakra component in dedicated sandbox.
模板
¥Template
使用以下模板快速入门
¥Use the following template to get started quickly
安装
¥Installation
所需的最低 Node 版本为 Node.20.x
安装依赖
¥Install dependencies
npm i @chakra-ui/react @emotion/react @emotion/cache react-frame-component
使用的附加包如下:
¥The additional packages used are:
-
react-frame-component
用于轻松创建 iframe -
@emotion/cache
用于创建样式的自定义插入点
添加代码片段
¥Add snippets
代码片段是预先构建的组件,你可以使用它们更快地构建 UI。使用 @chakra-ui/cli
属性,你可以将代码片段添加到你的项目中。
¥Snippets are pre-built components that you can use to build your UI faster.
Using the @chakra-ui/cli
you can add snippets to your project.
npx @chakra-ui/cli snippet add
更新 tsconfig
¥Update tsconfig
如果你使用的是 TypeScript,则需要更新 tsconfig 文件中的 compilerOptions
,使其包含以下选项:
¥If you're using TypeScript, you need to update the compilerOptions
in the
tsconfig file to include the following options:
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Bundler",
"skipLibCheck": true,
"paths": {
"@/*": ["./src/*"]
}
}
}
设置 iframe
¥Setup Iframe
创建一个 components/ui/iframe-provider.tsx
文件,使用 react-frame-component
包设置 iframe。
¥Create a components/ui/iframe-provider.tsx
file to setup the iframe using the
react-frame-component
package.
components/ui/iframe-provider.tsx
import {
ChakraProvider,
EnvironmentProvider,
defaultSystem,
} from "@chakra-ui/react"
import createCache from "@emotion/cache"
import { CacheProvider } from "@emotion/react"
import Iframe, { FrameContextConsumer } from "react-frame-component"
function memoize<T extends object, R>(func: (arg: T) => R): (arg: T) => R {
const cache = new WeakMap<T, R>()
return (arg: T) => {
if (cache.has(arg)) return cache.get(arg)!
const ret = func(arg)
cache.set(arg, ret)
return ret
}
}
const createCacheFn = memoize((container: HTMLElement) =>
createCache({ container, key: "frame" }),
)
export const IframeProvider = (props: React.PropsWithChildren) => {
const { children } = props
return (
<FrameContextConsumer>
{(frame) => {
const head = frame.document?.head
if (!head) return null
return (
<CacheProvider value={createCacheFn(head)}>
<EnvironmentProvider value={() => head.ownerDocument}>
<ChakraProvider value={defaultSystem}>
{children}
</ChakraProvider>
</EnvironmentProvider>
</CacheProvider>
)
}}
</FrameContextConsumer>
</Iframe>
)
}
设置提供者
¥Setup provider
使用应用根目录下 components/ui/provider
组件中生成的 Provider
组件封装你的应用。
¥Wrap your application with the Provider
component generated in the
components/ui/provider
component at the root of your application.
此提供程序包含以下内容:
¥This provider composes the following:
-
ChakraProvider
来自@chakra-ui/react
,用于样式系统 -
ThemeProvider
来自next-themes
,用于颜色模式
import { Provider } from "@/components/ui/provider"
import React from "react"
import ReactDOM from "react-dom/client"
import App from "./App"
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<Provider>
<App />
</Provider>
</React.StrictMode>,
)
使用 Iframe 提供程序
¥Use the IframeProvider
在应用中的任何组件中,使用 IframeProvider
组件封装它,以便在 iframe 内渲染它。
¥At any component in your application, wrap it with the IframeProvider
component to render it inside the iframe.
src/App.tsx
import { Button, Container, Heading, Stack } from "@chakra-ui/react"
import { IframeProvider } from "./components/ui/iframe-provider"
function App() {
return (
<Container py="8">
<Heading mb="5">Outside Iframe</Heading>
<Stack p="6" align="flex-start" border="1px solid red">
<Heading>Inside Iframe</Heading>
<Button>Click me</Button>
</Stack>
</IframeProvider>
</Container>
)
}
export default App
自定义
¥Customization
如果你使用 createSystem
函数创建了自定义主题,请确保将其传递给 IframeProvider
和 Provider
组件,以确保它在 iframe 内使用。
¥If you created a custom theme using the createSystem
function, ensure it's
passed to the IframeProvider
and Provider
components to ensure it's used
inside the iframe.
例如,假设你创建了一个自定义主题:
¥For example, let's say you created a custom theme:
export const system = createSystem(defaultConfig, {
theme: { colors: {} },
})
然后,将其传递给 IframeProvider
和 Provider
组件:
¥Then, pass it to the IframeProvider
and Provider
components:
<ChakraProvider value={system}>{/* ... */}</ChakraProvider>