为什么样式组件中的反引号可以访问 props.theme?

imy*_*mmy 3 reactjs styled-components

我有一个关于反引号如何在样式组件中工作的问题。

假设我使用它们定义并传递了一个主题ThemeProvider

const theme = {
  primary: '#df0000',
}

ReactDOM.render(
  <ThemeProvider theme={theme}>
    <App />
  </ThemeProvider>
  ,
  document.getElementById('root')
)
Run Code Online (Sandbox Code Playgroud)

我可以定义一个props.theme.primary在 App.js中访问的“样式 Div”,如下所示:

const App = props => {
  const Div = styled.div`
    background-color: ${props => props.theme.primary};
  `

  return (
    <>
      {console.log(props)}
      <h1>Welcome to React Parcel Micro App!</h1>
      <p>Hard to get more minimal than this React app.</p>
      <Div>lol</Div>
    </>
  )
}

export default App
Run Code Online (Sandbox Code Playgroud)

太好了,除了props.theme只能由 Div 访问,因为它${}在反引号内。console.log(props.theme)undefined。但是,如果我使用,export default withTheme(App)我会看到 console.log 打印主题。

样式组件中的反引号如何允许访问props.theme?

Wil*_*ill 5

如果存在,所有样式组件都可以从上下文内部访问主题。

无论您在哪里定义组件,它仍然可以在呈现时访问上下文。

这是当前实现的链接,您可以在其中看到它访问上下文。

  // Snippet from StyledComponent.js

  const theme = determineTheme(props, useContext(ThemeContext), defaultProps);
Run Code Online (Sandbox Code Playgroud)

但是您的问题特别是关于反引号的工作原理,所以这里是其余的答案:

样式组件使用template literals,特别是tagged templates功能。

这是MDN的摘录

标记模板

更高级的模板文字形式是标记模板。

标签允许您使用函数解析模板文字。标签函数的第一个参数包含一个字符串值数组。其余参数与表达式相关。

然后,标记函数可以对这些参数执行任何您希望的操作,并返回操作过的字符串。(或者,它可以返回完全不同的内容,如以下示例之一中所述。)

所以在你的例子中:

const Div = styled.div`
  background-color: ${props => props.theme.primary};
`

// is conceptually like calling the styled.div function with the following arguments: 

(
  ['background-color: ', ';'], // array of strings, 
  props => props.theme.primary // each expression is passed in as a new param
)
Run Code Online (Sandbox Code Playgroud)

一旦标记模板被拆分为字符串和函数。它被包裹在样式组件中。在渲染时,所有函数都使用样式组件的道具(以及上下文中的主题)调用。

使用 props 调用的每个函数都返回一个字符串。然后我们可以将字符串数组和函数的返回值拼接在一起,我们最终得到了最终的样式。

 ['background-color: ', ';'],
  props => props.theme.primary // returns a string e.g. "green"
Run Code Online (Sandbox Code Playgroud)

现在我们有了所有可以作为样式缝合在一起的字符串:

  'background-color: ' + 'green' + ';'
Run Code Online (Sandbox Code Playgroud)

在幕后进行了优化,但这是样式组件反引号如何工作的基础知识。

其中一位创建者有一篇很棒的博客文章,其中包含有关样式组件标记模板的更多信息。