自创ant-design-pro组件

ant design蚂蚁金服基于react打造的一个服务于企业级产品的UI框架。而ant design pro呢?就是基于Ant Design这个框架搭建的中后台管理控制台的脚手架。

话不多说,今天给大家分享一个自己写的一个组件。

源码如下:

index.tsx文件:

  1 import React,{Fragment} from 'react';
  2 import styles from './index.less'; 
  3 import undefined from '@/e2e/__mocks__/antd-pro-merge-less';
  4 export interface State {
  5     list:Array<any>,
  6     cacheList:Array<any>,
  7     eventIF:boolean,
  8 }
  9 export interface Props {
 10      style?:any,
 11      styleSon?:any,
 12      val?:valFrom,
 13      dataSource?:Array<dataSource>,
 14      onClickSon?:any,
 15      onMouseEnterSon?:any,
 16      onMouseLeaveSon?:any
 17  }
 18 interface valFrom{
 19     type?:TYPE|string,//动画类型
 20     direction?:DIRECTION|string,//方向
 21     time?:number,//时间 单位s
 22     delay?:number,//动画执行前的延时时间 单位s
 23     sonDelay?:number//列表子项动画延时
 24     domId?:string,//事件绑定dom id
 25     event?:EVENT|string,//动画执行事件
 26     hideModel?:boolean//背景是否显示
 27 
 28 } 
 29 export const enum TYPE{FADEIN}
 30 export const enum DIRECTION{TOP,BUTTOM,LEFT,REGIST,TOPLEFT,TOPREGIST,BUTTOMLEFT,BUTTOMREGIST}
 31 export const enum EVENT{CLICK,MOUSEENTER}
 32 interface dataSource{keys:any,title:any,style?:any}
 33 export class Father extends React.Component<Props, State> {
 34     constructor(props: Props) {
 35         super(props);
 36         this.state = { 
 37             list:[],//列表项
 38             cacheList:[],//暂时存储,观望是否绑定dom
 39             eventIF:false,//是否触发了event事件
 40         };
 41         if(this.props.val !== undefined){
 42             const val:valFrom = this.props.val;
 43             if(this.props.val.type != undefined && !(val.type===TYPE.FADEIN || val.type==="fadeIn")){
 44                 throw Error(`type定义错误:错误值为 ${val.type},type取值为{enum:TYPE,'fadeIn'}`,);
 45             }
 46             if(this.props.val.direction != undefined && !(val.direction === DIRECTION.TOP || val.direction === DIRECTION.BUTTOM || 
 47                 val.direction === DIRECTION.LEFT||val.direction === DIRECTION.REGIST || val.direction === DIRECTION.TOPLEFT ||
 48                 val.direction === DIRECTION.TOPREGIST || val.direction === DIRECTION.BUTTOMLEFT || val.direction === DIRECTION.BUTTOMREGIST ||
 49                 val.direction === 'top' || val.direction === 'buttom' || val.direction=== 'left' || val.direction === 'regist' ||
 50                 val.direction=== 'topLeft' || val.direction === 'topRegist' || val.direction === 'buttomLeft' || val.direction === 'buttomRegist')){
 51                 throw Error(`direction定义错误:错误值为 ${val.direction},direction取值为{enum:DIRECTION,'top','buttom','left','regist',
 52                 'topLeft','topRegist','buttomLeft','buttomRegist'}`);
 53             }
 54             window.onload = function(){
 55                 if(val.domId !== undefined){    
 56                     if(document.getElementById(val.domId)===undefined || document.getElementById(val.domId)===null){
 57                         throw Error(`指定id的DOM元素不存在!`,);
 58                     }
 59                     if(val.event === undefined){
 60                         console.warn(`指定DOM元素情况下未指定绑定事件event!`);
 61                     }
 62                 } 
 63             }
 64             if(val.event !== undefined){
 65                 if(!(val.event === EVENT.CLICK || val.event === EVENT.MOUSEENTER  || val.event === 'click' ||
 66                 val.event === 'mouseEnter')){
 67                     throw Error(`event定义错误:错误值为 ${val.event},event取值为{enum:EVENT,'click','mouseEnter'}`,);
 68                 }
 69                 if(val.domId === undefined){
 70                     console.warn(`绑定事件后未指定DOM元素!`);
 71                 }
 72             }
 73         }  
 74     }
 75     isWidth=(strs:Array<any>):number=>{
 76         let str : Array<string> = [];
 77         for(let i=0;i<strs.length;i++){
 78             if(strs[i].type!==undefined && strs[i].type===Son){
 79                 str.push(strs[i].props.children);
 80             }
 81         }
 82         let max:number = 0;
 83         let reg:RegExp =  /[\u4E00-\u9FA5\uF900-\uFA2D]/i;
 84         str.forEach(element => {
 85             let forMax = 0;
 86             for(let i=0;i<element.length;i++){
 87                 if(reg.test(element.charAt(i))){
 88                     forMax+=2;
 89                 }else{
 90                     forMax++;
 91                 }
 92             }
 93             if(forMax > max){
 94                 max = forMax;
 95             }
 96         });
 97         return max;
 98     }
 99     isWidth1=(maxWidth:number,data:Array<dataSource>):number=>{
100         let max:number = maxWidth;
101         let reg:RegExp =  /[\u4E00-\u9FA5\uF900-\uFA2D]/i;
102         data.forEach(element => {
103             let forMax = 0;
104             for(let i=0;i<element.title.length;i++){
105                 if(reg.test(element.title.charAt(i))){
106                     forMax+=2;
107                 }else{
108                     forMax++;
109                 }
110             }
111             if(forMax > max){
112                 max = forMax;
113             }
114         });
115         return max;
116     }
117     setList=():void=>{
118         //清零
119         this.state.list.length = 0;
120         const list = [...this.state.cacheList];
121         this.setState({list,eventIF:true});
122         //解除绑定
123         if(this.props.val != undefined && this.props.val.domId != undefined){
124             let dom:any = document.getElementById(this.props.val.domId);
125             let event:string = "click";
126             if(this.props.val.event === EVENT.MOUSEENTER){
127                 event = "mouseenter";
128             }
129             dom.removeEventListener(event,this.setList);        
130         }
131     }
132     bindEvent=(val:any):void=>{
133         if(this.props.val != undefined && this.props.val.domId != undefined && this.props.val.event != undefined){
134             const dom:any = document.getElementById(this.props.val.domId);
135             let event:string = "click";
136             if(this.props.val.event === EVENT.MOUSEENTER){
137                 event = "mouseenter";
138             }
139             dom.addEventListener(event,this.setList);                
140         }
141     }
142     render() { 
143         //默认动画效果
144         const defVal:valFrom = {
145             type:TYPE.FADEIN,
146             direction:DIRECTION.LEFT,
147             time:.5,
148             sonDelay:.1,
149             delay:0,
150         };
151         const defV = {...defVal,...this.props.val}
152         //Son项数
153         let index:number = 0;
154         //最大文字占格
155         let width:number=0;
156         //字体大小
157         let fontSize:number = 13;
158         //Son高度
159         let formatHeight:number = 26;
160         //Father及Son宽度
161         let formatWidth:number = 0;
162        
163         let sonStr:any = this.props.children;
164         // //宽高自适应
165         if(this.props.children != undefined){
166             width = this.isWidth(sonStr);
167         }
168         if(this.props.dataSource != undefined){
169             width = this.isWidth1(width,this.props.dataSource);
170         }
171         fontSize = this.props.style!==undefined && this.props.style.fontSize!==undefined?Number.parseInt(this.props.style.fontSize):13;
172         formatHeight = fontSize*2;
173         formatWidth = fontSize*width*0.6;
174         
175         //绑定dom后是否隐藏模板
176         let hideModel = "visible";
177         if(!this.state.eventIF){
178             //清零
179             this.state.list.length = 0;
180             this.state.cacheList.length = 0;
181             //子项写入
182             if(this.props.children != null && this.props.children != undefined){  
183                 for(let i=0;i<sonStr.length;i++){
184                     if(sonStr[i].type!==undefined && sonStr[i].type===Son){
185                         this.state.cacheList.push(<List title={sonStr[i].props.children} style={sonStr[i].props.style} styleSon={this.props.styleSon}
186                         animation={defV} index={index++} formatHeight={formatHeight}
187                         formatWidth = {formatWidth} keys={this.props.children[i].props.keys !==undefined?
188                         this.props.children[i].props.keys:Number.MAX_VALUE-i} onClick={this.props.children[i].props.onClick}
189                         onClickSon={this.props.onClickSon} onMouseEnter={this.props.children[i].props.onMouseEnter}
190                         onMouseEnterSon={this.props.onMouseEnterSon} onMouseLeave={this.props.children[i].props.onMouseLeave}
191                         onMouseLeaveSon={this.props.onMouseLeaveSon}/>);
192                     }
193                 }
194             }
195             if(this.props.dataSource !== undefined){
196                 for(let i=0;i<this.props.dataSource.length;i++){
197                     this.state.cacheList.push(<List title={this.props.dataSource[i].title} style={this.props.dataSource[i].style} index={index++}
198                     styleSon={this.props.styleSon} animation={defV} formatHeight={formatHeight} formatWidth = {formatWidth} keys=
199                     {this.props.dataSource[i].keys}/>);
200                 }
201             }
202             //无dom绑定
203             if(defV.domId ===undefined || defV.event ===undefined){
204                 for(let i =0;i<this.state.cacheList.length;i++){
205                     this.state.list.push(this.state.cacheList[i]);
206                 }
207                 
208             }else{
209                 //有dom绑定
210                 if(this.props.val!=undefined && this.props.val.hideModel){
211                     hideModel = "hidden";
212                 }
213                 //事件绑定
214                 const _this  = this;
215                 //切换菜单后window.onload不会执行,但dom已经重置
216                 if(this.props.val != undefined && this.props.val.domId != undefined && this.props.val.event != undefined && 
217                 document.getElementById(this.props.val.domId)==null){
218                     let interval = window.setInterval(()=>{
219                         let dom:any = null;
220                         if(_this.props.val!=undefined && _this.props.val.domId != undefined){
221                             dom = document.getElementById(_this.props.val.domId);
222                         }
223                         if(dom !== null && dom !==undefined && dom !=="null"){
224                             _this.bindEvent(defV);
225 
226                             window.clearInterval(interval); 
227                         } 
228                     }, 100);        
229                 }
230             }
231         }else {
232             index = this.state.list.length;
233         }
234         
235         //Father默认样式
236 
237         const defFatherStyle:any = {
238             border:"1px solid #91D5FF",
239             backgroundColor: "#E6F7FF",
240             fontSize:"13px",
241             color:"#000",
242             paddimg:`${fontSize}px`,
243             height: `${formatHeight*index+2}px`,
244             width:`${formatWidth+2}px`,
245             visibility:`${hideModel}`
246         }
247         const style = {...defFatherStyle,...this.props.style};
248         return (
249             <Fragment>
250                 <div style={style} className={styles.fDiv}>
251                     <ul className={styles.ul}>
252                         {this.state.list}
253                     </ul>
254                 </div>
255             </Fragment>
256          );
257     }
258 }
259 export class Son extends React.Component<{style?:any,keys?:any,onClick?:any,onMouseEnter?:any,onMouseLeave?:any}, {}> {
260 }
261 class List extends React.Component<{title:string,style?:any,styleSon?:any,animation:valFrom,keys:any,index:number,formatHeight:number,
262     formatWidth:number,onClick?:any,onClickSon?:any,onMouseEnter?:any,onMouseEnterSon?:any,onMouseLeave?:any,onMouseLeaveSon?:any},{}> {
263     click = (key:any,title:any)=>{
264         if(this.props.onClick !== undefined){
265             this.props.onClick(key,title);
266         }else if(this.props.onClickSon !== undefined){
267             this.props.onClickSon(key,title);
268         }
269     }
270     mouseEnter = (key:any,title:any)=>{
271         if(this.props.onMouseEnter !== undefined){
272             this.props.onMouseEnter(key,title);
273         }else if(this.props.onMouseEnterSon !== undefined){
274             this.props.onMouseEnterSon(key,title);
275         }
276     }
277     mouseLeave = (key:any,title:any)=>{
278         if(this.props.onMouseLeave !== undefined){
279             this.props.onMouseLeave(key,title);
280         }else if(this.props.onMouseLeaveSon !== undefined){
281             this.props.onMouseLeaveSon(key,title);
282         }
283     }
284 
285 
286 
287     render() {
288         const val:valFrom = this.props.animation;
289         const style = {animation:'',animationDelay:'0s'};
290         
291         //加载页面后直接执行
292         if(val.type === TYPE.FADEIN && val.direction === DIRECTION.TOP || val.type === 'fadeIn' && val.direction === 'top'
293         || val.type === TYPE.FADEIN && val.direction === 'top' || val.type === 'fadeIn' && val.direction === DIRECTION.TOP){
294             style.animation= `${styles.fadeInTop} ${val.time}s forwards`;
295         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.BUTTOM || val.type === 'fadeIn' && val.direction === 'buttom'
296         || val.type === TYPE.FADEIN && val.direction === 'buttom' || val.type === 'fadeIn' && val.direction === DIRECTION.BUTTOM){
297             style.animation = `${styles.fadeInButtom} ${val.time}s forwards`;       
298         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.LEFT || val.type === 'fadeIn' && val.direction === 'left'
299         || val.type === TYPE.FADEIN && val.direction === 'left' || val.type === 'fadeIn' && val.direction === DIRECTION.LEFT){
300         style.animation = `${styles.fadeInLeft} ${val.time}s forwards`;
301         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.REGIST || val.type === 'fadeIn' && val.direction === 'regist'
302         || val.type === TYPE.FADEIN && val.direction === 'regist' || val.type === 'fadeIn' && val.direction === DIRECTION.REGIST){
303             style.animation = `${styles.fadeInRegist} ${val.time}s forwards`;
304         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.TOPLEFT || val.type === 'fadeIn' && val.direction === 'topLeft'
305         || val.type === TYPE.FADEIN && val.direction === 'topLeft' || val.type === 'fadeIn' && val.direction === DIRECTION.TOPLEFT){
306             style.animation = `${styles.fadeInTopLeft} ${val.time}s forwards`;
307         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.TOPREGIST || val.type === 'fadeIn' && val.direction === 'topRegist'
308         || val.type === TYPE.FADEIN && val.direction === 'topRegist' || val.type === 'fadeIn' && val.direction === DIRECTION.TOPREGIST){
309             style.animation = `${styles.fadeInTopRegist} ${val.time}s forwards`;
310         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.BUTTOMLEFT || val.type === 'fadeIn' && val.direction === 'buttomLeft'
311         || val.type === TYPE.FADEIN && val.direction === 'buttomLeft' || val.type === 'fadeIn' && val.direction === DIRECTION.BUTTOMLEFT){
312             style.animation = `${styles.fadeInButtomLeft} ${val.time}s forwards`;
313         }else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.BUTTOMREGIST || val.type === 'fadeIn' && val.direction === 'buttomRegist'
314         || val.type === TYPE.FADEIN && val.direction === 'buttomRegist' || val.type === 'fadeIn' && val.direction === DIRECTION.BUTTOMREGIST){
315             style.animation = `${styles.fadeInButtomRegist} ${val.time}s forwards`;
316         }
317         if(val.sonDelay !== undefined && val.delay !== undefined){
318             style.animationDelay = `${this.props.index*val.sonDelay+val.delay}s`;
319         }
320         //Son默认样式
321         const defStyle:any = {
322             textAlign: "center",
323             width:`${this.props.formatWidth}px`,
324             height:`${this.props.formatHeight}px`,
325             lineHeight:`${this.props.formatHeight}px`,
326         }
327         const sty = {...defStyle,...this.props.styleSon,...this.props.style,...style};
328         return ( 
329             <li className={styles.li} style={sty} key={this.props.keys} onClick={this.click.bind(this,this.props.keys,this.props.title)}
330             onMouseEnter = {this.mouseEnter.bind(this,this.props.keys,this.props.title)} onMouseLeave=
331             {this.mouseLeave.bind(this,this.props.keys,this.props.title)}>{this.props.title}</li>
332          );
333     }
334 }

index.less文件:

  1 @top:200px;
  2 @left:400px;
  3 .fDiv,.li,.ul,body,div{
  4     padding: 0px;
  5     margin: 0px;
  6     border: 0px;
  7 }
  8 .fDiv{
  9     position: relative;
 10 }
 11 .li{
 12     list-style:none;
 13     visibility:hidden;
 14     cursor: pointer; 
 15 }
 16 li:hover{
 17     background-color: #A1E5FF;
 18 }
 19 .ul{
 20     position: absolute;
 21     z-index: 999;
 22     display: inline-block;
 23 }
 24 @keyframes fadeInTop{
 25     0%{
 26         opacity: 0;
 27         margin-top: @top;
 28         visibility:visible;
 29     }
 30     100%{
 31         opacity: 1;
 32         margin-top: 0px;
 33         visibility:visible;
 34     }
 35 }
 36 @keyframes fadeInButtom{
 37     0%{
 38         opacity: 0;
 39         margin-top: -@top;
 40         visibility:visible;
 41     }
 42     100%{
 43         opacity: 1;
 44         margin-top: 0px;
 45         visibility:visible;
 46     }
 47 }
 48 @keyframes fadeInLeft{
 49     0%{
 50         opacity: 0;
 51         margin-left: @left;
 52         visibility:visible;
 53     }
 54     100%{
 55         opacity: 1;
 56         margin-left: 0px;
 57         visibility:visible;
 58     }
 59 }
 60 @keyframes fadeInRegist{
 61     0%{
 62         opacity: 0;
 63         margin-left: -@left;
 64         visibility:visible;
 65     }
 66     100%{
 67         opacity: 1;
 68         margin-left: 0px;
 69         visibility:visible;
 70     }
 71 }
 72 @keyframes fadeInTopLeft{
 73     0%{
 74         opacity: 0;
 75         margin-top: @top;
 76         margin-left: @left;
 77         visibility:visible;
 78     }
 79     100%{
 80         opacity: 1;
 81         margin-top: 0px;
 82         margin-left: 0px;
 83         visibility:visible;
 84     }
 85 }
 86 @keyframes fadeInTopRegist{
 87     0%{
 88         opacity: 0;
 89         margin-top: @top;
 90         margin-left: -@left;
 91         visibility:visible;
 92     }
 93     100%{
 94         opacity: 1;
 95         margin-top: 0px;
 96         margin-left: 0px;
 97         visibility:visible;
 98     }
 99 }
100 @keyframes fadeInButtomLeft{
101     0%{
102         opacity: 0;
103         margin-top: -@top;
104         margin-left: @left;
105         visibility:visible;
106     }
107     100%{
108         opacity: 1;
109         margin-top: 0px;
110         margin-left: 0px;
111         visibility:visible;
112     }
113 }
114 @keyframes fadeInButtomRegist{
115     0%{
116         opacity: 0;
117         margin-top: -@top;
118         margin-left: -@left;
119         visibility:visible;
120     }
121     100%{
122         opacity: 1;
123         margin-top: 0px;
124         margin-left: 0px;
125         visibility:visible;
126     }
127 }

API如下:

猜你喜欢

转载自www.cnblogs.com/chengpu/p/web1.html