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

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

源码如下:

index.tsx文件:

 import React,{Fragment} from 'react';
import styles from './index.less';
import undefined from '@/e2e/__mocks__/antd-pro-merge-less';
export interface State {
list:Array<any>,
cacheList:Array<any>,
eventIF:boolean,
}
export interface Props {
style?:any,
styleSon?:any,
val?:valFrom,
dataSource?:Array<dataSource>,
onClickSon?:any,
onMouseEnterSon?:any,
onMouseLeaveSon?:any
}
interface valFrom{
type?:TYPE|string,//动画类型
direction?:DIRECTION|string,//方向
time?:number,//时间 单位s
delay?:number,//动画执行前的延时时间 单位s
sonDelay?:number//列表子项动画延时
domId?:string,//事件绑定dom id
event?:EVENT|string,//动画执行事件
hideModel?:boolean//背景是否显示 }
export const enum TYPE{FADEIN}
export const enum DIRECTION{TOP,BUTTOM,LEFT,REGIST,TOPLEFT,TOPREGIST,BUTTOMLEFT,BUTTOMREGIST}
export const enum EVENT{CLICK,MOUSEENTER}
interface dataSource{keys:any,title:any,style?:any}
export class Father extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
list:[],//列表项
cacheList:[],//暂时存储,观望是否绑定dom
eventIF:false,//是否触发了event事件
};
if(this.props.val !== undefined){
const val:valFrom = this.props.val;
if(this.props.val.type != undefined && !(val.type===TYPE.FADEIN || val.type==="fadeIn")){
throw Error(`type定义错误:错误值为 ${val.type},type取值为{enum:TYPE,'fadeIn'}`,);
}
if(this.props.val.direction != undefined && !(val.direction === DIRECTION.TOP || val.direction === DIRECTION.BUTTOM ||
val.direction === DIRECTION.LEFT||val.direction === DIRECTION.REGIST || val.direction === DIRECTION.TOPLEFT ||
val.direction === DIRECTION.TOPREGIST || val.direction === DIRECTION.BUTTOMLEFT || val.direction === DIRECTION.BUTTOMREGIST ||
val.direction === 'top' || val.direction === 'buttom' || val.direction=== 'left' || val.direction === 'regist' ||
val.direction=== 'topLeft' || val.direction === 'topRegist' || val.direction === 'buttomLeft' || val.direction === 'buttomRegist')){
throw Error(`direction定义错误:错误值为 ${val.direction},direction取值为{enum:DIRECTION,'top','buttom','left','regist',
'topLeft','topRegist','buttomLeft','buttomRegist'}`);
}
window.onload = function(){
if(val.domId !== undefined){
if(document.getElementById(val.domId)===undefined || document.getElementById(val.domId)===null){
throw Error(`指定id的DOM元素不存在!`,);
}
if(val.event === undefined){
console.warn(`指定DOM元素情况下未指定绑定事件event!`);
}
} 
}
if(val.event !== undefined){
if(!(val.event === EVENT.CLICK || val.event === EVENT.MOUSEENTER || val.event === 'click' ||
val.event === 'mouseEnter')){
throw Error(`event定义错误:错误值为 ${val.event},event取值为{enum:EVENT,'click','mouseEnter'}`,);
}
if(val.domId === undefined){
console.warn(`绑定事件后未指定DOM元素!`);
}
}
}
}
isWidth=(strs:Array<any>):number=>{
let str : Array<string> = [];
for(let i=;i<strs.length;i++){
if(strs[i].type!==undefined && strs[i].type===Son){
str.push(strs[i].props.children);
}
}
let max:number = ;
let reg:RegExp = /[\u4E00-\u9FA5\uF900-\uFA2D]/i;
str.forEach(element => {
let forMax = ;
for(let i=;i<element.length;i++){
if(reg.test(element.charAt(i))){
forMax+=;
}else{
forMax++;
}
}
if(forMax > max){
max = forMax;
}
});
return max;
}
isWidth1=(maxWidth:number,data:Array<dataSource>):number=>{
let max:number = maxWidth;
let reg:RegExp = /[\u4E00-\u9FA5\uF900-\uFA2D]/i;
data.forEach(element => {
let forMax = ;
for(let i=;i<element.title.length;i++){
if(reg.test(element.title.charAt(i))){
forMax+=;
}else{
forMax++;
}
}
if(forMax > max){
max = forMax;
}
});
return max;
}
setList=():void=>{
//清零
this.state.list.length = ;
const list = [...this.state.cacheList];
this.setState({list,eventIF:true});
//解除绑定
if(this.props.val != undefined && this.props.val.domId != undefined){
let dom:any = document.getElementById(this.props.val.domId);
let event:string = "click";
if(this.props.val.event === EVENT.MOUSEENTER){
event = "mouseenter";
}
dom.removeEventListener(event,this.setList);
}
}
bindEvent=(val:any):void=>{
if(this.props.val != undefined && this.props.val.domId != undefined && this.props.val.event != undefined){
const dom:any = document.getElementById(this.props.val.domId);
let event:string = "click";
if(this.props.val.event === EVENT.MOUSEENTER){
event = "mouseenter";
}
dom.addEventListener(event,this.setList);
}
}
render() {
//默认动画效果
const defVal:valFrom = {
type:TYPE.FADEIN,
direction:DIRECTION.LEFT,
time:.,
sonDelay:.,
delay:,
};
const defV = {...defVal,...this.props.val}
//Son项数
let index:number = ;
//最大文字占格
let width:number=;
//字体大小
let fontSize:number = ;
//Son高度
let formatHeight:number = ;
//Father及Son宽度
let formatWidth:number = ; let sonStr:any = this.props.children;
// //宽高自适应
if(this.props.children != undefined){
width = this.isWidth(sonStr);
}
if(this.props.dataSource != undefined){
width = this.isWidth1(width,this.props.dataSource);
}
fontSize = this.props.style!==undefined && this.props.style.fontSize!==undefined?Number.parseInt(this.props.style.fontSize):;
formatHeight = fontSize*;
formatWidth = fontSize*width*0.6; //绑定dom后是否隐藏模板
let hideModel = "visible";
if(!this.state.eventIF){
//清零
this.state.list.length = ;
this.state.cacheList.length = ;
//子项写入
if(this.props.children != null && this.props.children != undefined){
for(let i=;i<sonStr.length;i++){
if(sonStr[i].type!==undefined && sonStr[i].type===Son){
this.state.cacheList.push(<List title={sonStr[i].props.children} style={sonStr[i].props.style} styleSon={this.props.styleSon}
animation={defV} index={index++} formatHeight={formatHeight}
formatWidth = {formatWidth} keys={this.props.children[i].props.keys !==undefined?
this.props.children[i].props.keys:Number.MAX_VALUE-i} onClick={this.props.children[i].props.onClick}
onClickSon={this.props.onClickSon} onMouseEnter={this.props.children[i].props.onMouseEnter}
onMouseEnterSon={this.props.onMouseEnterSon} onMouseLeave={this.props.children[i].props.onMouseLeave}
onMouseLeaveSon={this.props.onMouseLeaveSon}/>);
}
}
}
if(this.props.dataSource !== undefined){
for(let i=;i<this.props.dataSource.length;i++){
this.state.cacheList.push(<List title={this.props.dataSource[i].title} style={this.props.dataSource[i].style} index={index++}
styleSon={this.props.styleSon} animation={defV} formatHeight={formatHeight} formatWidth = {formatWidth} keys=
{this.props.dataSource[i].keys}/>);
}
}
//无dom绑定
if(defV.domId ===undefined || defV.event ===undefined){
for(let i =;i<this.state.cacheList.length;i++){
this.state.list.push(this.state.cacheList[i]);
} }else{
//有dom绑定
if(this.props.val!=undefined && this.props.val.hideModel){
hideModel = "hidden";
}
//事件绑定
const _this = this;
//切换菜单后window.onload不会执行,但dom已经重置
if(this.props.val != undefined && this.props.val.domId != undefined && this.props.val.event != undefined &&
document.getElementById(this.props.val.domId)==null){
let interval = window.setInterval(()=>{
let dom:any = null;
if(_this.props.val!=undefined && _this.props.val.domId != undefined){
dom = document.getElementById(_this.props.val.domId);
}
if(dom !== null && dom !==undefined && dom !=="null"){
_this.bindEvent(defV); window.clearInterval(interval);
}
}, );
}
}
}else {
index = this.state.list.length;
} //Father默认样式 const defFatherStyle:any = {
border:"1px solid #91D5FF",
backgroundColor: "#E6F7FF",
fontSize:"13px",
color:"#000",
paddimg:`${fontSize}px`,
height: `${formatHeight*index+}px`,
width:`${formatWidth+}px`,
visibility:`${hideModel}`
}
const style = {...defFatherStyle,...this.props.style};
return (
<Fragment>
<div style={style} className={styles.fDiv}>
<ul className={styles.ul}>
{this.state.list}
</ul>
</div>
</Fragment>
);
}
}
export class Son extends React.Component<{style?:any,keys?:any,onClick?:any,onMouseEnter?:any,onMouseLeave?:any}, {}> {
}
class List extends React.Component<{title:string,style?:any,styleSon?:any,animation:valFrom,keys:any,index:number,formatHeight:number,
formatWidth:number,onClick?:any,onClickSon?:any,onMouseEnter?:any,onMouseEnterSon?:any,onMouseLeave?:any,onMouseLeaveSon?:any},{}> {
click = (key:any,title:any)=>{
if(this.props.onClick !== undefined){
this.props.onClick(key,title);
}else if(this.props.onClickSon !== undefined){
this.props.onClickSon(key,title);
}
}
mouseEnter = (key:any,title:any)=>{
if(this.props.onMouseEnter !== undefined){
this.props.onMouseEnter(key,title);
}else if(this.props.onMouseEnterSon !== undefined){
this.props.onMouseEnterSon(key,title);
}
}
mouseLeave = (key:any,title:any)=>{
if(this.props.onMouseLeave !== undefined){
this.props.onMouseLeave(key,title);
}else if(this.props.onMouseLeaveSon !== undefined){
this.props.onMouseLeaveSon(key,title);
}
} render() {
const val:valFrom = this.props.animation;
const style = {animation:'',animationDelay:'0s'}; //加载页面后直接执行
if(val.type === TYPE.FADEIN && val.direction === DIRECTION.TOP || val.type === 'fadeIn' && val.direction === 'top'
|| val.type === TYPE.FADEIN && val.direction === 'top' || val.type === 'fadeIn' && val.direction === DIRECTION.TOP){
style.animation= `${styles.fadeInTop} ${val.time}s forwards`;
}else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.BUTTOM || val.type === 'fadeIn' && val.direction === 'buttom'
|| val.type === TYPE.FADEIN && val.direction === 'buttom' || val.type === 'fadeIn' && val.direction === DIRECTION.BUTTOM){
style.animation = `${styles.fadeInButtom} ${val.time}s forwards`;
}else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.LEFT || val.type === 'fadeIn' && val.direction === 'left'
|| val.type === TYPE.FADEIN && val.direction === 'left' || val.type === 'fadeIn' && val.direction === DIRECTION.LEFT){
style.animation = `${styles.fadeInLeft} ${val.time}s forwards`;
}else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.REGIST || val.type === 'fadeIn' && val.direction === 'regist'
|| val.type === TYPE.FADEIN && val.direction === 'regist' || val.type === 'fadeIn' && val.direction === DIRECTION.REGIST){
style.animation = `${styles.fadeInRegist} ${val.time}s forwards`;
}else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.TOPLEFT || val.type === 'fadeIn' && val.direction === 'topLeft'
|| val.type === TYPE.FADEIN && val.direction === 'topLeft' || val.type === 'fadeIn' && val.direction === DIRECTION.TOPLEFT){
style.animation = `${styles.fadeInTopLeft} ${val.time}s forwards`;
}else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.TOPREGIST || val.type === 'fadeIn' && val.direction === 'topRegist'
|| val.type === TYPE.FADEIN && val.direction === 'topRegist' || val.type === 'fadeIn' && val.direction === DIRECTION.TOPREGIST){
style.animation = `${styles.fadeInTopRegist} ${val.time}s forwards`;
}else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.BUTTOMLEFT || val.type === 'fadeIn' && val.direction === 'buttomLeft'
|| val.type === TYPE.FADEIN && val.direction === 'buttomLeft' || val.type === 'fadeIn' && val.direction === DIRECTION.BUTTOMLEFT){
style.animation = `${styles.fadeInButtomLeft} ${val.time}s forwards`;
}else if(val.type === TYPE.FADEIN && val.direction === DIRECTION.BUTTOMREGIST || val.type === 'fadeIn' && val.direction === 'buttomRegist'
|| val.type === TYPE.FADEIN && val.direction === 'buttomRegist' || val.type === 'fadeIn' && val.direction === DIRECTION.BUTTOMREGIST){
style.animation = `${styles.fadeInButtomRegist} ${val.time}s forwards`;
}
if(val.sonDelay !== undefined && val.delay !== undefined){
style.animationDelay = `${this.props.index*val.sonDelay+val.delay}s`;
}
//Son默认样式
const defStyle:any = {
textAlign: "center",
width:`${this.props.formatWidth}px`,
height:`${this.props.formatHeight}px`,
lineHeight:`${this.props.formatHeight}px`,
}
const sty = {...defStyle,...this.props.styleSon,...this.props.style,...style};
return (
<li className={styles.li} style={sty} key={this.props.keys} onClick={this.click.bind(this,this.props.keys,this.props.title)}
onMouseEnter = {this.mouseEnter.bind(this,this.props.keys,this.props.title)} onMouseLeave=
{this.mouseLeave.bind(this,this.props.keys,this.props.title)}>{this.props.title}</li>
);
}
}

index.less文件:

 @top:200px;
@left:400px;
.fDiv,.li,.ul,body,div{
padding: 0px;
margin: 0px;
border: 0px;
}
.fDiv{
position: relative;
}
.li{
list-style:none;
visibility:hidden;
cursor: pointer;
}
li:hover{
background-color: #A1E5FF;
}
.ul{
position: absolute;
z-index: ;
display: inline-block;
}
@keyframes fadeInTop{
%{
opacity: ;
margin-top: @top;
visibility:visible;
}
%{
opacity: ;
margin-top: 0px;
visibility:visible;
}
}
@keyframes fadeInButtom{
%{
opacity: ;
margin-top: -@top;
visibility:visible;
}
%{
opacity: ;
margin-top: 0px;
visibility:visible;
}
}
@keyframes fadeInLeft{
%{
opacity: ;
margin-left: @left;
visibility:visible;
}
%{
opacity: ;
margin-left: 0px;
visibility:visible;
}
}
@keyframes fadeInRegist{
%{
opacity: ;
margin-left: -@left;
visibility:visible;
}
%{
opacity: ;
margin-left: 0px;
visibility:visible;
}
}
@keyframes fadeInTopLeft{
%{
opacity: ;
margin-top: @top;
margin-left: @left;
visibility:visible;
}
%{
opacity: ;
margin-top: 0px;
margin-left: 0px;
visibility:visible;
}
}
@keyframes fadeInTopRegist{
%{
opacity: ;
margin-top: @top;
margin-left: -@left;
visibility:visible;
}
%{
opacity: ;
margin-top: 0px;
margin-left: 0px;
visibility:visible;
}
}
@keyframes fadeInButtomLeft{
%{
opacity: ;
margin-top: -@top;
margin-left: @left;
visibility:visible;
}
%{
opacity: ;
margin-top: 0px;
margin-left: 0px;
visibility:visible;
}
}
@keyframes fadeInButtomRegist{
%{
opacity: ;
margin-top: -@top;
margin-left: -@left;
visibility:visible;
}
%{
opacity: ;
margin-top: 0px;
margin-left: 0px;
visibility:visible;
}
}

API如下:

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

最新文章

  1. PHP读取EXCEL时间
  2. Ue4的容器(数据结构)
  3. 免费的HTML5连载来了《HTML5网页开发实例详解》连载(二)
  4. Java Web文件上传
  5. VS2010编写动态链接库DLL及单元测试用例,调用DLL测试正确性
  6. JavaScript HTML DOM---遗漏知识再整理(向html添加/删除元素,改变内容和css)
  7. insertAfter()
  8. 查看Ubuntu操作系统位数
  9. C++得到最大的int值
  10. Python内置函数(51)——hasattr
  11. [Codeforces 863E]Turn Off The TV
  12. React学习笔记(一)- 环境搭建
  13. Linux 压缩某个文件夹命令
  14. SpringBoot入门 (十四) Security安全控制
  15. Kafka:ZK+Kafka+Spark Streaming集群环境搭建(六)针对spark2.2.1以yarn方式启动spark-shell抛出异常:ERROR cluster.YarnSchedulerBackend$YarnSchedulerEndpoint: Sending RequestExecutors(0,0,Map(),Set()) to AM was unsuccessful
  16. C#学习笔记(22)——C#创建文本文件txt并追加写入数据
  17. 无插件用Terminal/TotalTerminal的开当前finder位置
  18. JavaScript权威指南——跳转语句
  19. KMP(2)
  20. NET Framework 4.0无法安装!

热门文章

  1. Codeforces 734D. Anton and Chess(模拟)
  2. codeforces 805 D. Minimum number of steps(数学)
  3. Requests库整理
  4. 决胜Flutter 第一章 熟悉战场
  5. buuctf 随便注 writeup
  6. 【Redis】基础学习概览【汇总】
  7. ssh的秘钥认证
  8. java第一次测验
  9. Maven依赖配置和依赖范围
  10. 使用vitamio长时间播放崩溃的另类处理