【问题标题】:Create SVG components with scoped CSS使用作用域 CSS 创建 SVG 组件
【发布时间】:2019-02-22 14:04:59
【问题描述】:

我正在创建将呈现各种 SVG 的 React 组件:

const Close = ({
  fill, width, height, float,
}) => (
  <svg width={ `${width}px` } height={ `${height}px` } viewBox="0 0 14.48 14.48" style={ { float: `${float}`, cursor: 'pointer' } }>
    <title>x</title>
    <g id="Layer_2" data-name="Layer 2">
      <g id="Background">
        <line style={ { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 } } x1="14.13" y1="0.35" x2="0.35" y2="14.13" />
        <line style={ { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 } } x1="14.13" y1="14.13" x2="0.35" y2="0.35" />
      </g>
    </g>
  </svg>
);

能够提供该组件的各种属性来控制尺寸,颜色等非常方便......

然而,我没有一个好的解决方案是以 DRY 方式处理样式。请注意line 元素与style 具有相同的值。我现在将它们内联编写,因为如果我添加了一个嵌入式样式表,那么我会与我在页面上其他地方渲染的其他 SVG 发生类名冲突(我们的 SVG 软件一遍又一遍地使用相同的类)。

&lt;style scoped&gt; 已从规范中删除:https://github.com/whatwg/html/issues/552

Edge 还不支持Shadow DOM:https://caniuse.com/#feat=shadowdomv1

范围样式还有其他替代方法吗?

【问题讨论】:

  • 嗨@Mister。你为什么不去 css-in-js。 ?
  • @MisterEpic 我对你在找什么有点困惑。每个 SVG 都非常独特,那么为什么要在它们之间共享样式呢?
  • css-modules (github.com/css-modules/css-modules) 怎么样?它符合您的要求吗?
  • 对于范围样式,请考虑使用 shadow DOM。对于边缘,使用 polyfills
  • @MisterEpic OP 去哪儿了?

标签: css reactjs svg


【解决方案1】:

实际上,如果我在你的位置,我当然会使用字体而不是 SVG,但是对于你的确切问题,我更喜欢在箭头函数中使用常量变量,如下所示:

import React from 'react';

const Close = ({ fill, width, height, float }) => {
  const constStyle = { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 };

  return (
    <svg
      width={`${width}px`}
      height={`${height}px`}
      viewBox="0 0 14.48 14.48"
      style={{ float: `${float}`, cursor: 'pointer' }}
    >
      <title>x</title>
      <g id="Layer_2" data-name="Layer 2">
        <g id="Background">
          <line style={constStyle} x1="14.13" y1="0.35" x2="0.35" y2="14.13" />
          <line style={constStyle} x1="14.13" y1="14.13" x2="0.35" y2="0.35" />
        </g>
      </g>
    </svg>
  );
};

export default Close;

即使,我将线尺寸变量设为props,但我不知道你的具体情况。

希望这个答案对你有所帮助。

【讨论】:

    【解决方案2】:

    要结合两全其美,您可以创建一个外部样式文件,就像创建 CSS 一样,但要使用导出的样式对象。然后,您可以将其导入到任何需要它的文件中。

    例如,主文件:

    import React, { Component } from 'react';
    import { render } from 'react-dom';
    import * as Styles from './svgstyles';
    
    class App extends Component {
      render() {
        return (
          <div>
            <svg width="100" height="200" viewBox="0 0 100 200">  
              <rect x="0" y="0" width="10" height="10" style={Styles.style1} />
              <rect x="15" y="0" width="10" height="10" style={Styles.style2} />
              <rect x="30" y="0" width="10" height="10" style={Styles.style3} />
              <rect x="45" y="0" width="10" height="10" style={Styles.style4} />
              <rect x="0" y="15" width="10" height="10" style={Styles.style4} />
              <rect x="15" y="15" width="10" height="10" style={Styles.style3} />
              <rect x="30" y="15" width="10" height="10" style={Styles.style2} />
              <rect x="45" y="15" width="10" height="10" style={Styles.style1} />
            </svg>
          </div>
        );
      }
    }
    
    render(<App />, document.getElementById('root'));
    

    还有一个外部样式文件:

    export const style1 = {
      stroke: 'red',
      strokeWidth: "1",
      fill: "blue",
    }
    
    export const style2 = {
      stroke: 'red',
      strokeWidth: "1",
      fill: "green",
    }
    
    export const style3 = {
      stroke: 'red',
      strokeWidth: "1",
      fill: "yellow",
    }
    
    export const style4 = {
      ...style3,
      fill: "pink",
    }
    

    Live example here

    【讨论】:

      【解决方案3】:

      如果你只是想干掉代码,你可以创建一个样式对象并重用它:

      const Close = ({
                       fill, width, height, float,
                     }) => {
        const style = { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 }
        return (
          <svg width={ `${width}px` } height={ `${height}px` } viewBox="0 0 14.48 14.48" style={ { float: `${float}`, cursor: 'pointer' } }>
            <title>x</title>
            <g id="Layer_2" data-name="Layer 2">
              <g id="Background">
                <line style={ style } x1="14.13" y1="0.35" x2="0.35" y2="14.13" />
                <line style={ style } x1="14.13" y1="14.13" x2="0.35" y2="0.35" />
              </g>
            </g>
          </svg>
        );
      }
      

      这也将导致性能小幅提升,因为在每个渲染周期中创建的对象更少。

      【讨论】:

      • 是的,这样更好,但这是一个小例子。我在现实世界中的 SVG 有多种内联样式。
      猜你喜欢
      • 1970-01-01
      • 2015-07-07
      • 1970-01-01
      • 2016-04-01
      • 2011-06-17
      • 2017-08-20
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      相关资源
      最近更新 更多