代码之家  ›  专栏  ›  技术社区  ›  Mister Epic

使用范围CSS创建SVG组件

  •  7
  • Mister Epic  · 技术社区  · 7 年前

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

    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>
    );
    

    它非常方便,能够提供各种归因于该组件的控制尺寸,颜色等。

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

    <style scoped> 已从规范中删除: https://github.com/whatwg/html/issues/552

    边缘尚不支持阴影DOM: https://caniuse.com/#feat=shadowdomv1

    范围样式还有其他选择吗?

    3 回复  |  直到 7 年前
        1
  •  1
  •   pgsandstrom    7 年前

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

    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>
      );
    }
    

    由于在每个渲染周期中创建的对象较少,因此这也会导致性能的小幅提高。

        2
  •  2
  •   Ted    7 年前

    要结合两者的优点,您可以创建一个外部样式文件,就像您创建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
  •  0
  •   AmerllicA    7 年前

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

    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 但我不知道你到底是怎么回事。

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