【问题标题】:ReactJS Component Architecture Problems / Nested Components or Single Component ManagerReactJS 组件架构问题 / 嵌套组件或单组件管理器
【发布时间】:2017-10-20 11:56:46
【问题描述】:

我目前正在用 ReactJS 构建一个图标组件,它可能有 50-100 个图标,全部使用 SVG 和路径数据。

我的情况是,我想知道哪条路线最适合我前进,以及为什么这条路线会是更好的选择。我已经想到了两种可行的方案,并且都可以看到两者的好处。


选项 1

  • 创建一个名为“Icon”的组件
  • 获取一个名为“name”的道具(这将引用图标名称)
  • 根据道具名称显示适当的svg
  • 所有图标的单个组件


选项 2

  • 创建一个名为“Icon”的组件
  • 为每个图标创建单独的组件,例如(ArrowLeft、Hamburger)
  • 单个组件继承'Icon'作为父组件
  • 父组件保存所有 SVG 信息
  • 子组件只保存路径数据
  • 50-100 个图标组件


我会考虑使用 Option 1 作为我的文件系统的更清洁的方法,我可以想象一个包的文件大小对于生产就绪代码来说更小。

我已经开始编写这两个选项的代码,并且非常希望得到一些输入。特别是如果我还没有想到更好的方法。

这里有一些代码:-


选项 1

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled, { ThemeProvider } from 'styled-components';
import _ from 'lodash';
import '../../global.js';
import * as variable from '../../variables.js';

const iconList = {
    navigation: {
        arrowUp: 'path data here',
        hamburger: 'path data here'
  }
}

class Icon extends Component {
    constructor(props) {
        super(props);
    }

    render() {

        let width, height, data, name;

        width = this.props.width === undefined ? '25' : this.props.width;
        height = this.props.height === undefined ? '25' : this.props.height;

        name = this.props.name;

        _.forEach(iconList, function(value, key) {
            data = _.get(value, [name]);
        });


        const icon = <svg xmlns="http://www.w3.org/2000/svg" width={width} height={height} viewBox="0 0 25 25">
                         <path fill={this.props.color} d={data} fillRule="evenodd" />
                    </svg>;

        return (
                <IconStyle>
                    {icon}
                </IconStyle>
        )

    }
}

export default Icon;

选项 2 - (Icon.js)

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import styled, { ThemeProvider } from 'styled-components'

import '../../global.js';
import * as variable from '../../variables.js';

const IconStyle = styled.div `
    display:inline-block;
`;

class Icons extends Component {
    constructor(props) {
        super(props);
    }

    render() {

        let width, height;

        width = this.props.width === undefined ? '25' : this.props.width;
        height = this.props.height === undefined ? '25' : this.props.height;


        const icon = <svg xmlns="http://www.w3.org/2000/svg" width={width} height={height} viewBox="0 0 25 25">
                         <path fill={this.props.color} d={this.props.data} fillRule="evenodd" />
                    </svg>;

        return (
                <IconStyle>
                    {icon}
                </IconStyle>
        )

    }
}


export default Icons;

选项 2 - Hamburger.js(继承图标)

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

import '../../../global.js';
import * as variable from '../../../variables.js';
import Icon from '../Icon';

class NavigationHamburger extends Component {
    constructor(props) {
        super(props);
    }

    render() {


        let data = "M6.34 8.14c-.45 0-.8-.36-.8-.8 0-.45.35-.8.8-.8h12c.44 0 .8.35.8.8 0 .44-.36.8-.8.8h-12zm12 8.4c.44 0 .8.35.8.8 0 .44-.36.8-.8.8h-12c-.45 0-.8-.36-.8-.8 0-.45.35-.8.8-.8h12zm0-5c.44 0 .8.35.8.8 0 .44-.36.8-.8.8h-12c-.45 0-.8-.36-.8-.8 0-.45.35-.8.8-.8h12z";

        return (
                <Icon data={data} {...this.props} />           
        )

    }
}

NavigationHamburger.PropTypes = {
    data: PropTypes.string,
    color: PropTypes.color,
    width: PropTypes.boolean,
    height: PropTypes.boolean
}

export default NavigationHamburger;

使用 选项 2 我只需调用组件使用

&lt;NavigationHamburger width={30} height={30} color="#000"/>

【问题讨论】:

    标签: javascript reactjs svg


    【解决方案1】:

    我也会选择first方法:

    1. 方法

      • + 更少的代码
      • + 更易于维护(更快地添加新图标)
      • + 无代码重复

      • - 名称中可能出现拼写错误(也许您可以使用某种 javascript 枚举)

    2. 方法

      • + 更易于使用(已定义组件,无名称)

      • - 难以维护(更改每个文件中的代码)

      • - 大量代码
      • - 不可扩展

    所以我会采取第一种方法,但我也会添加这个文件以便于使用:

    IconTypes.js:

    const IconTypes = {
      HAMBURGER: 'hamburger'
    }
    
    export default IconTypes;
    

    现在您已经消除了拼写错误的机会,因为您收到了一个 lint 错误。您现在可以这样调用图标(在导入 Icon 和 IconType 类之后):

    <Icon name={iconTypes.HAMBURGER} width={30} height={30} color="#000" />
    

    我希望这个答案能告诉你一些观点并帮助你做出决定。

    【讨论】:

      【解决方案2】:

      选项 1选项 2 好很多。首先,可重用性发挥了最大作用。将有一个组件,您每次都将使用不同的道具来使用它。其次,如果你选择Option 2,文件结构会很混乱。凌乱,我的意思是每个图标都有一个单独的文件,并且在捆绑和编译时会花费一些时间。为了更好,我建议您将此路径映射到另一个文件,而不是在组件中进行:

      const iconList = {
        navigation: {
          arrowUp: 'path data here',
          hamburger: 'path data here'
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-07-03
        • 1970-01-01
        • 1970-01-01
        • 2021-05-17
        • 1970-01-01
        • 1970-01-01
        • 2019-04-08
        • 1970-01-01
        • 2018-11-06
        相关资源
        最近更新 更多