Semantic-UI的React实现(二):CSS类构造模块

开发 开发工具
Semantic-UI使用了更简单的类名声明。用过Bootstrap的同学都会被其复杂的类名标签折磨过,例如一个简单的按键样式,不论颜色或是大小,都需要btn-前缀声明。

[[173783]]

更简单的类名标签

Semantic-UI使用了更简单的类名声明。用过Bootstrap的同学都会被其复杂的类名标签折磨过,例如一个简单的按键样式,不论颜色或是大小,都需要btn-前缀声明:

  1. <button type="button" class="btn btn-primary btn-lg active">Primary button</button> 

在Semantic-UI中,类名更接近自然表述:

  1. <button class="ui blue large active button">Blue Button</button> 

语义化的样式声明

样式名并不是对某种组件进行的类型声明,可以通用到其他组件中。例如对于Label(标签)组件,也可用与button相同的CSS类声明其样式:

  1. <div class="ui blue large active label">Blue Label</div> 

这样的好处是显而易见的,CSS类名语义化,刚方便使用和学习。

类名构造模块的实现

从以上细节可以看出,每个组件的类声明均可由公用模块生成,每个组件仅仅声明本模块可使用的Props即可。以Button举例如下:

  1. import PropHelper from './PropHelper'
  2. import UiElement from './UiElement'
  3. ... 
  4.  
  5. let PROP_TYPES = ['primary''size''color''basic''active', ...]; 
  6.  
  7. class Button extends UiElement { 
  8.      
  9.     static propTypes = { 
  10.         ...PropHelper.createPropTypes(PROP_TYPES) 
  11.     }; 
  12.      
  13.     render() { 
  14.          
  15.         let style = this.createElementStyle(this.props, PROP_TYPES, 'button'); 
  16.          
  17.         return ( 
  18.             <div id={this.props.id} className={style} tabIndex='0'
  19.                 {this.props.children} 
  20.             </div> 
  21.         ); 
  22.     } 
  23.      
  24.     ... 
  25.  

Button类声明了其可以使用的class类名,通过共通处理生成style即可。生成style的共同处理,由PropsHelper类负责完成。

PropsHelper

PropsHelper类主要的职责有两个:

  1. 生成各组件所需的class类集合
  2. 生成各组件的props属性检查定义

PropsHelper作为工具类,相关处理过程中并无状态参与,方法应该声明为静态方法(static)。

props属性检查

Semantci-UI中的所有class类属性的集合是可枚举的,这些属性直接在PropsHelper中定义即可:

  1. const BOOL_PROPS = ['ui''active''disabled''circular', ...]; 
  2. const STRING_PROPS = ['icon''appendClass', ...], 
  3. const NUMBER_PROPS = ['column''wide', ...], 
  4. const COLLECTION_PROPS = ['color''size''position', ...];  

对于每个组件的属性检查定义,可以遍历传入的属性,并根据名字找到该属性的PropTypes定义。

  1. class PropsHelper { 
  2.      
  3.     ... 
  4.      
  5.     /** 
  6.      * 生成属性检查 
  7.      */ 
  8.     static createPropTypes(propTypes) { 
  9.          
  10.         let result = {}; 
  11.         propTypes.forEach(function(typeName, index) { 
  12.      
  13.             if (BOOL_PROPS.indexOf(typeName) >= 0) { 
  14.               result[typeName] = React.PropTypes.bool; 
  15.             } 
  16.             else if (STRING_PROPS.indexOf(typeName) >= 0) { 
  17.               result[typeName] = React.PropTypes.string; 
  18.             } 
  19.             else if (NUMBER_PROPS.indexOf(typeName) >= 0) { 
  20.               result[typeName] = React.PropTypes.number; 
  21.             } 
  22.             else if (COLLECTION_PROPS.indexOf(typeName) >= 0) { 
  23.               result[typeName] = React.PropTypes.oneOf(PROPS_VALUES[typeName]); 
  24.             } 
  25.         }); 
  26.          
  27.         return result; 
  28.     } 
  29.  

class类集合组装

与createPropTypes同样的思路,将传入的组件props遍历一遍,找到各自prop属性的类型定义,根据类型定义编辑和组装该组件的class类集合。

  1. class PropsHelper { 
  2.  
  3.     ... 
  4.      
  5.     /** 
  6.      * 根据属性生成引用的class 
  7.      */ 
  8.     static createStyle(props, types) { 
  9.  
  10.     let style = ''
  11.     for (let i = 0; i < types.length; i++) { 
  12.       let type = types[i]; 
  13.       if (props.hasOwnProperty(type)) { 
  14.         style += this.formatStyleValue(props[type], type); 
  15.       } 
  16.     } 
  17.  
  18.     return style; 
  19.   } 
  20.    
  21.   /** 
  22.    * 格式化属性对应的class 
  23.    */ 
  24.   static formatStyleValue(value, type) { 
  25.  
  26.     // 如果是数字型属性 
  27.     if (NUMBER_PROPS.indexOf(type) >= 0) { 
  28.       return ' ' + this.getNumberStr(value) + ' ' + type; 
  29.     } 
  30.     else if (COLLECTION_PROPS.indexOf(type) >= 0) { 
  31.       if (type == 'size'return ' ' + value; 
  32.       return ' ' + value + ' ' + type; 
  33.     } 
  34.     else if (BOOL_PROPS.indexOf(type) >= 0) { 
  35.  
  36.       if (!value) return ''
  37.  
  38.       if (type == 'imaged'return ' image'
  39.       if (type == 'iconed'return ' icon'
  40.       if (type == 'long'return ' long scrolling'
  41.       if (type == 'equalWidth'return ''
  42.       return ' ' + type; 
  43.     } 
  44.     else if (STRING_PROPS.indexOf(type) >= 0) { 
  45.       return ' ' + value; 
  46.     } 
  47.     else { 
  48.       return ''
  49.     } 
  50.   } 
  51.  

这样实现以后,各组件在各自属性的定义和class类声明的处理时获得了两方面的益处:

  1. 属性统一管理,不用再各自声明
  2. 代码复用性和耦合性更佳(特别是在复杂组件的使用中)
责任编辑:庞桂玉 来源: segmentfault
相关推荐

2016-10-18 21:26:29

Semantic-UIReact架构

2016-10-18 21:39:59

Semantic-UIReact基本元素组件

2016-10-18 21:45:53

Semantic-UIReactJavascript

2021-01-19 12:16:10

CSS前端UI

2012-07-10 01:47:14

代码架构设计

2009-08-21 18:05:16

黑客模块化主板硬件

2021-05-10 10:18:54

工具代码开发

2016-11-23 16:48:20

react-nativandroidjavascript

2022-05-11 07:50:15

React UI组件库前端

2023-01-29 08:00:00

Instagram滤镜图片编辑

2021-11-09 07:26:14

CssMaterialUI React

2020-03-02 09:26:16

JavaScript程序员JSON

2011-05-16 10:35:02

jQuery

2022-09-02 08:00:00

CSS开发框架

2015-04-20 17:07:38

模块化数据中心湖南省电科院华为

2015-07-31 09:28:53

React场景探索

2021-05-21 06:13:35

React Hooks react-refrReact

2013-08-20 18:18:55

CSS模块化Normalize.c

2020-10-28 09:12:48

React架构Hooks

2021-05-31 07:40:48

函数实例化策略
点赞
收藏

51CTO技术栈公众号