【问题标题】:Alternative to createGlobalStyle from styled-components that can also be importable从也可以导入的样式组件中创建全局样式的替代方法
【发布时间】:2021-10-31 18:40:42
【问题描述】:

我们目前正在加载字体和其他几个像这样的全局样式:

import { createGlobalStyle } from 'styled-components';

export default createGlobalStyle`
  @font-face {
     font-family: 'Name';
     font-style: normal;
     font-weight: 400;
     font-display: swap;
     src: url(https://fonts.gstatic.com/s/name/v12/iJWZBXyIfDnIV5PNhY1KTN7Z-Yh-B4iFU0U1Z4Y.woff2) format('woff2');
  }

  // more fonts..
}

在每个_app.tsx(来自 repo 中的每个项目)我们只是

import GlobalStyle from @our-company/ui;
// few other imports

const AppProviders = ({ children, messages, locale }: Props): JSX.Element => {
  return (
    <IntlProvider
      locale={locale || 'en-GB'}
      key={locale}
      messages={messages[locale]}
      defaultLocale="en-GB"
    >
      <GlobalStyle />
      <DsThemeProvider
        locale={locale}
      >
        {children}
      </DsThemeProvider>
    </IntlProvider>
  );
};

但我们注意到,在单击复选框元素时,GlobalStyle 会导致不必要的字体重新加载(尝试将其放在 .css 中并加载它,然后再也不会发生)。

知道如何在不使用 styled-components 的情况下将此样式导出为 GlobalStyle 名称,这样我们就不必更改项目中所有应用程序中的所有 import 吗?

【问题讨论】:

  • 您是否可以将 styled-components createGlobalStyle 替换为从 css 文件中导入字体配置的组件?
  • 不完全,我试图不重构存储库中的所有应用程序(有很多)
  • 我的意思是将@our-company/ui 中的GlobalStyle 替换为从css 文件中导入其样式的组件,从而使其“静态”而不是每次都重新加载,我现在更清楚了吗?
  • 就是这样!感谢您用可以理解的语言表达出来????
  • 嗯,好的,这样会有帮助吗?

标签: reactjs styled-components


【解决方案1】:

为什么你不创建 main.css 并将其导入你的 index.css 或 app.css ,它的下载和缓存在用户浏览器上,这样你就不需要再使用全局样式的组件了

【讨论】:

  • 如果可能的话,我会尽量不重构存储库中的所有应用程序。^^
【解决方案2】:

您似乎正在寻找类似injectGlobal 的东西:

import { injectGlobal } from 'styled-components';

injectGlobal`
  /* your @font-face stuff here */
`

这似乎很适合您的情况,因为从使用 createGlobalStyle 的现有结构过渡到使用它的结构相对容易。

在您的情况下,代码如下所示:

import { injectGlobal } from 'styled-components';

injectGlobal`
  @font-face {
     font-family: 'Name';
     font-style: normal;
     font-weight: 400;
     font-display: swap;
     src: url(https://fonts.gstatic.com/s/name/v12/iJWZBXyIfDnIV5PNhY1KTN7Z-Yh-B4iFU0U1Z4Y.woff2) format('woff2');
  }

  // more fonts..
}

如果您希望使用与呈现&lt;GlobalStyle /&gt; 的任何代码向后兼容的解决方案,您可以在injectGlobal 代码旁边包含一个空组件作为默认导出作为权宜之计解决方案:

export default () => null;

这能解决您的问题吗?

【讨论】:

  • 我不能让它工作,你能发布整个文件的样子吗?这是我目前的测试pastebin.com/dc3u4xmi 它爆炸了呵呵
  • @ToniMichelCaubet 您导出的组件是错误的 - 正如我上面建议的那样,它应该只是 const GlobalStyles = () =&gt; null;。尝试渲染 injectGlobal 是不行的。
  • 还是不行..pastebin.com/tLNMkDvz"export 'default' (reexported as 'GlobalStyle') was not found in './fonts'
  • @ToniMichelCaubet 保留export default GlobalStyle; 否则无法被其他文件导入。
  • 你试过了吗? wait - compiling... event - compiled successfully error - Error: Cannot create styled-component for component:
【解决方案3】:

你也可以直接在JS文件里面绑定样式

var stylingObject = {
  div: {
    color: "red",
    border: "1px solid red"
  }, input: {
    margin: "2px",
    padding: "5px"
  }
}

function App() {
  return (
      <div style={stylingObject.div}>
        <input style={stylingObject.input} type="text" />
      </div>
  );
}

【讨论】:

    【解决方案4】:

    最初我希望导入一些带有在那里定义的字体的 CSS 文件,然后只导入它,这样它就会影响整个页面,显然因为 react 的工作方式这样的事情是不可能的,因为它只会发生在导入的组件不在进行导入的组件中。

    styled-components 中的createGlobalStyle 每次渲染的原因也是由于 react 的工作原理 - 当我们为“类似组件”(或实际组件)对象设置样式时,就像每个 react 组件一样,它不是静态的并且只渲染需要的时候。即使我们在页面加载时强制渲染它,它也不是同一个(因为在每个页面上我们单独渲染它),所以按照 React 的标准,跟上当前配置似乎是不可能的。

    如果我们想让样式静态或“更多”静态,我们必须:

    • 在每个页面中单独导入它们 - 让我们进行重大重构
    • 或使用createGlobalStyle(允许我们使用我们已经创建的样式组件组件)或在主应用程序组件中导入一个主css文件,如下例所示:

    globalStyles.js

    import { createGlobalStyle } from 'styled-components';
     
    const GlobalStyle = createGlobalStyle`
      body {
        margin: 0;
        padding: 0;
        background: teal;
        font-family: Open-Sans, Helvetica, Sans-Serif;
      }
    `;
     
    export default GlobalStyle;
    

    App.js

    import React, { Fragment } from 'react';
    import GlobalStyle from './theme/globalStyle';
    import Content from './components/Content';
     
    function App() {
      return (
        <Fragment>
          <GlobalStyle />
          <Content />
        </Fragment>
      );
    }
     
    export default App;
    

    【讨论】:

    • 但这正是我们目前拥有代码的方式(您可以在问题中看到它)(我想您忘记添加此代码?“或在主应用程序组件中导入主 css 文件,如下面的例子")
    • 这里的区别是您使用样式组件(createGlobalStyle),但您在应用程序主组件中使用它而不是在特定组件中使用它,因此无需根据主组件重新加载(如导航栏)始终呈现相同的内容并贯穿应用程序的整个生命周期
    • @ToniMichelCaubet 如果这个答案对你有帮助,请接受它
    • 抱歉,我看不出它与我当前的代码相比有何帮助..
    • 如果你只在主组件中导入它,它将从一开始就被渲染,消除每个新组件上的重新渲染
    【解决方案5】:

    如果您像我们在迁移时那样有一个相当大的全局样式表,您可以使用 styled-components css 方法来利用 styled-components (css) IDE 语法突出显示和 linting,您还可以执行以下操作:

    import React from 'react'
    import { createGlobalStyle, css } from 'styled-components'
    
    const Reset = css`
      * {
        box-sizing: border-box;
      }
    `
    
    const Accessibility = css`
      .hidden {
        display: none !important;
        visibility: hidden;
      }
    `
    
    const BaseStyles = createGlobalStyle`
      ${Reset};
      ${Accessibility};
    `
    
    export const GlobalStyles = () => (
      <>
        <BaseStyles />
      </>
    )
    

    导入 GlobalStyles 并作为{children} 的兄弟渲染

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-15
      • 2021-07-07
      • 1970-01-01
      • 2020-11-24
      • 2020-02-23
      • 2017-04-02
      • 1970-01-01
      • 2021-03-09
      相关资源
      最近更新 更多