当前位置: 首页 > 科技观察

Semantic-UI的React实现(四):基本元素组件的共通处理(父类)实现

时间:2023-03-13 17:39:41 科技观察

Semantic-UI的React实现(四):基础元素组件的通用处理(父类)实现因为没有复杂的交互,只有CSS类的编辑组装,所以实现原理比较简单。但是想要把简单的东西变得简洁,往往并不简单。抽象与封装如果要将几十个基础组件简洁高效地封装起来,那么对组件相同的处理部分进行抽象是非常有必要的。在ES6中,js加入了class关键字(当然,这只是一个语法糖,背后的处理原理还是原型集),有了这个关键字,js在抽象和封装上比以前更高级了.迈出了一步。在用“继承”的思想考虑问题的时候,组件的公共处理显然可以通过继承一个公共的父类来完成(通常我更喜欢用接口而不是继承,但是js不好学,而且我不知道如何实现接口继承)。继承之后,所有基础组件的如下处理都可以通过父类的处理完成:编辑组装CSS类渲染组件本身封装了事件系统的方法回调实现细节编辑组装CSS类在第二篇中提到系列文章中,基本组件的CSS编辑和组装都是在PropsHelper中实现的,所有的细节对外都是隐藏的,组件只需要声明相关的属性即可。如Header使用的属性://propertydefinitionconstPROP_TYPES=PropsHelper.getDefaultPropTypes().concat(['size','sub','dividing','floated','aligned','inverted','inline','颜色']);这些可用属性的声明,连同Button组件实例的props,可以编辑和组装所需的CSS类名集合。在Header的render方法中,只需要调用:render(){//渲染元素letstyle=this.createElementStyle(this.props,PROP_TYPES)+'header';returnsuper.render(style);}生成样式的具体细节,在Header的父类UiElement中:/***生成元素的样式*/createElementStyle(props,propsDef){...returnPropsHelper.createStyle(props,propsDef)+''+style;}渲染组件也是常见的处理实现,作为子类的基础组件,只需要调用super.render:render(style,children,props){returnReact.createElement(this.props.as,//组件的html标签(默认div){id:this.props.id,//组件IDclassName:style,//组件类...this.getEventCallback(),//Eventcallbackdeclaration...props//Componentotherprops(用于生成class的props不需要)},children?children:this.props.children);}一开始并没有这样的实现,渲染每个组件的进程仍然留在组件的各自渲染中。但是随着组件数量的增加,发现这部分代码的复用性很强。如果有特殊组件不适用于此流程,只需在组件中重写此方法即可。这也大大提高了整体代码的可维护性。事件系统的回调函数还在实现中。我的目标是任何组件只需要声明,不需要在组件内部实现回调,回调处理通过公共方法实现。比如一个Button要使用onClick方法,直接声明:Btn,而无需在Button组件内部实现onClick回调处理。(其实实现不了,因为Button的渲染过程是在其父类UiElement中实现的)constEVENT_CALLBACK=['onKeyDown','onKeyPress','onKeyUp','onFocus','onBlur','onChange','onInput','onSubmit','onClick','onContextMenu','onDoubleClick','onDrag','onDragEnd','onDragEnter','onDragExit','onDragLeave','onDragOver','onDragStart','onDrop','onMouseDown','onMouseEnter','onMouseLeave','onMouseMove','onMouseOut','onMouseOver','onMouseUp','onSelect','onTouchCancel','onTouchEnd','onTouchMove','onTouchStart','onScroll','onWheel','onLoad','onError','onTransitionEnd','onAnimationStart','onAnimationEnd','onAnimationIteration',];事件系统的回调在构造函数中定义如下:constructor(props){super(props);leteventProps={};for(letkeyinprops){if(key.indexOf('on')==0&&EVENT_CALLBACK.indexOf(key)>=0){eventProps[key]=this.handleCallback.bind(this,key);}}this.eventCallbacks=eventProps;}如果这个组件传入的props包含'onXXX'并且这个'onXXX'是定义在EVENT_CALLBACK中,就认为组件声明了一个事件系统回调,然后UiElement会绑定这个回调的具体处理。处理过程实现如下:handleCallback(callback,e){if(this.props.callback){this.props.callback(e);}}回想一下,在UiElement中,实现了三类公共函数,用于基础调用的组件类:编辑实现组装CSS类渲染组件自身的方法回调封装事件系统后,提取出基本组件类的相同处理,只留下一些声明性代码。例如Header组件的实现简化为:importReactfrom'react';importPropsHelperfrom'./PropsHelper';importUiElementfrom'./UiElement';//属性定义constPROP_TYPES=PropsHelper.getDefaultPropTypes().concat(['size','sub','dividing','floated','aligned','inverted','inline','color']);/***Header组件*/classHeaderextendsUiElement{//类型定义staticpropTypes={...PropsHelper.createPropTypes(PROP_TYPES)};//默认值定义staticdefaultProps={...PropsHelper.getDefaultPropsValue(PROP_TYPES)};/***获取渲染内容*/render(){//渲染元素letstyle=this.createElementStyle(this.props,PROP_TYPES)+'header';returnsuper.render(style);}}exportdefaultHeader;这样做的好处很明显:简化实现代码提高可读性封装公共处理提高可维护性通过方法重写保持可扩展性上几篇,基本组件的封装应该说完了,接下来几篇打算讲复杂组件的实现.完成所有组件的封装后,打算扩展一些复杂组件的功能(代码比较丑,只能实现更多的功能。总之,肯定和官方不一样/(ㄒoㄒ)/~~)。