Repository: hengg/styled-components-docs-zh Branch: master Commit: 11ad9800bb50 Files: 5 Total size: 30.2 KB Directory structure: gitextract_sei4q2ee/ ├── API_Reference.md ├── Advanced.md ├── Basics.md ├── LICENSE └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: API_Reference.md ================================================ ## Primary ================================================ FILE: Advanced.md ================================================ # 高级 ## 主题 `styled-component`提供``包装组件以支持主题.``通过`context`API 为其后代组件提供主题.在其渲染树中的所有组件都能够访问主题. 下面的示例通过创建一个按钮组件来说明如何传递主题: ```jsx // Define our button, but with the use of props.theme this time const Button = styled.button` font-size: 1em; margin: 1em; padding: 0.25em 1em; border-radius: 3px; /* Color the border and text with theme.main */ color: ${props => props.theme.main}; border: 2px solid ${props => props.theme.main}; `; // We are passing a default theme for Buttons that arent wrapped in the ThemeProvider Button.defaultProps = { theme: { main: "palevioletred" } } // Define what props.theme will look like const theme = { main: "mediumseagreen" }; render(
); ``` ### 函数主题 theme prop 也可以传递一个函数.该函数接收渲染树上级``所传递的主题. 通过这种方式可以使 themes 形成上下文. 下面的示例说明了如何通过第二个``来交换 `background`和`foreground`的颜色. 函数`invertTheme` 接收上级 theme 后创建一个新的 theme. ```jsx // Define our button, but with the use of props.theme this time const Button = styled.button` color: ${props => props.theme.fg}; border: 2px solid ${props => props.theme.fg}; background: ${props => props.theme.bg}; font-size: 1em; margin: 1em; padding: 0.25em 1em; border-radius: 3px; `; // Define our `fg` and `bg` on the theme const theme = { fg: "palevioletred", bg: "white" }; // This theme swaps `fg` and `bg` const invertTheme = ({ fg, bg }) => ({ fg: bg, bg: fg }); render(
); ``` ### 在`styled-components`外使用主题 如果需要在`styled-components`外使用主题,可以使用高阶组件`withTheme`: ```jsx import { withTheme } from 'styled-components' class MyComponent extends React.Component { render() { console.log('Current theme: ', this.props.theme) // ... } } export default withTheme(MyComponent) ``` ### theme prop 主题可以通过`theme prop`传递给组件.通过使用`theme prop`可以绕过或重写`ThemeProvider`所提供的主题. ```jsx // Define our button const Button = styled.button` font-size: 1em; margin: 1em; padding: 0.25em 1em; border-radius: 3px; /* Color the border and text with theme.main */ color: ${props => props.theme.main}; border: 2px solid ${props => props.theme.main}; `; // Define what main theme will look like const theme = { main: "mediumseagreen" }; render(
); ``` ## Refs 通过传递`ref prop`给 styled component 将获得: - 底层 DOM 节点 (如果 styled 的对象是基本元素如 div) - React 组件实例 (如果 styled 的对象是 React Component) ```jsx const Input = styled.input` padding: 0.5em; margin: 0.5em; color: palevioletred; background: papayawhip; border: none; border-radius: 3px; `; class Form extends React.Component { constructor(props) { super(props); this.inputRef = React.createRef(); } render() { return ( { this.inputRef.current.focus() }} /> ); } } render(
); ``` >注意 > >v3 或更低的版本请使用 [innerRef prop](https://www.styled-components.com/docs/api#innerref-prop) instead. ## 安全性 因为 styled-components 允许使用任意的输入作为插值使用,我们必须谨慎处理输入使其无害.使用用户输入作为样式可能导致用户浏览器中的CSS文件被攻击者替换. 以下这个例子展示了糟糕的输入导致的 API 被攻击: ```jsx // Oh no! The user has given us a bad URL! const userInput = '/api/withdraw-funds' const ArbitraryComponent = styled.div` background: url(${userInput}); /* More styles here... */ ` ``` 请一定谨慎处理!这虽然是一个明显的例子,但是CSS注入可能隐式的发生并且产生不良影响.有些旧版本的 IE 甚至会在 url 声明中执行 JavaScript. There is an upcoming standard to sanitize CSS from JavaScript有一个即将推出的标准,可以用于无害化 JavaScript 中的 CSS, [`CSS.escape`](https://developer.mozilla.org/en-US/docs/Web/API/CSS/escape). 这个标准还没有被浏览器很好的支持,因此建议使用 [`polyfill by Mathias Bynens`](https://github.com/mathiasbynens/CSS.escape) . ## Existing CSS 如果想将 styled-components 和现有的 CSS 共同使用,有很多实现的细节必须注意到. styled-components 通过类生成实际的样式表,并通过`className prop`将这些类附加到响应的 DOM 节点. 运行时它会被注入到 document 的 head 末尾. ### Styling normal React components 使用`styled(MyComponent)` 声明, `MyComponent` 却不接收传入的 `className` prop, 则样式并不会被呈现. 为避免这个问题,请确保组件接收 `className` 并传递给 DOM 节点: ```jsx class MyComponent extends React.Component { render() { // Attach the passed-in className to the DOM node return
} } ``` 对于已存在类名的组件,可以将其余传入的类合并: ```jsx class MyComponent extends React.Component { render() { // Attach the passed-in className to the DOM node return
} } ``` ### Issues with specificity 将`styled-components`类与全局类混用,可能会导致出乎意料的结果.如果一个`property`在两个类中被定义且两个类的优先级相同,则后者会覆盖前者. ```jsx // MyComponent.js const MyComponent = styled.div`background-color: green;`; // my-component.css .red-bg { background-color: red; } // For some reason this component still has a green background, // even though you're trying to override it with the "red-bg" class! ``` 上述例子中`styled-components`类的样式覆盖了全局类,因为`styled-components`在运行时向``末尾注入样式. 一种解决方式是提高全局样式的优先级: ```jsx /* my-component.css */ .red-bg.red-bg { background-color: red; } ``` ### 避免与第三方样式和脚本的冲突 如果在一个不能完全控制的页面上部署`styled-components`,可能需要采取措施确保 component styles 不与 host page 上其他样式冲突. 常见的问题是优先级相同,例如 host page 上持有如下样式: ```jsx body.my-body button { padding: 24px; } ``` 因为其包含一个类名和两个标签名,它的优先级要高于 styled component 生成的一个类名的选择器: ```jsx styled.button` padding: 16px; ` ``` 没有让 styled component 完全不受 host page 样式影响的办法.但是可以通过[`babel-plugin-styled-components-css-namespace`](https://github.com/QuickBase/babel-plugin-styled-components-css-namespace)来提高样式的优先级, 通过它可以为 styled components 的类指定一个命名空间. 一个好的命名空间,譬如`#my-widget`,可以实现styled-components 在 一个 `id="my-widget"`的容器中渲染, 因为 id 选择器的优先级总是高于类选择器. 一个罕见的问题是同一页面上两个`styled-components`实例的冲突.通过在 code bundle 中定义 `process.env.SC_ATTR` 可以避免这个问题. 它将覆盖 `