自创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,
  6     cacheList:Array,
  7     eventIF:boolean,
  8 }
  9 export interface Props {
 10      style?:any,
 11      styleSon?:any,
 12      val?:valFrom,
 13      dataSource?:Array,
 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 {
 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):number=>{
 76         let str : Array<string> = [];
 77         for(let i=0;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){
 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):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){
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){
184                     if(sonStr[i].type!==undefined && sonStr[i].type===Son){
185                         this.state.cacheList.push(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(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             
250                 
251
    252 {this.state.list} 253
254
255
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
  • 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}
  • 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如下:

    自创ant-design-pro组件_第1张图片

    自创ant-design-pro组件_第2张图片

    注意:动画进入选择的类型目前只有fadeIn(渐入),有人可能会说这个可以不要,但是如果要继续拓展的话这个属性就必不可少了,比如拓展增强、轨迹、旋转、无效果等。这些拓展稍显有些麻烦,由于我只是当练习react与typescript来写就没有拓展,但不是不能拓展。

     

    你可能感兴趣的