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来写就没有拓展,但不是不能拓展。

自创ant-design-pro组件的更多相关文章

  1. 【后台管理系统】—— Ant Design Pro组件使用(二)

    一.关联表单项 - 动态增删输入框Input        封装子组件 class ParamsInputArray extends React.Component{ constructor(prop ...

  2. 【后台管理系统】—— Ant Design Pro组件使用(一)

    一.搜索Search      搜索框 <Search placeholder="请输入关键字" defaultValue={kw && kw != 'nul ...

  3. Ant Design Pro路由传值

    Ant Design Pro 路由传值 了解Ant Design Pro组件间通讯原理的小伙伴肯定都知道,两个页面之间可以通过Models进行传值,在以往的传值过程中,我都是直接将需要的值直接一股脑的 ...

  4. ant design pro 当中改变ant design 组件的样式和 数据管理

    ant design pro 简介 官网简介 链接 https://pro.ant.design/docs/getting-started-cn 项目结构 https://github.com/ant ...

  5. 阿里开源项目之Ant Design Pro

    本篇文章主要包含的内容有三个方面. 第一.Ant Design Pro简介; 第二.Ant Design Pro能做什么; 第三.初步使用; 我相信通过这三个方面的讲解能让你大概知道Ant Desig ...

  6. ant design pro (十四)advanced 使用 CLI 工具

    一.概述 原文地址:https://pro.ant.design/docs/cli-cn 为了更好以及高效的开发效率,我们提供了配套的 ant-design-pro-cli 工具. pro cli 提 ...

  7. ant design pro (十三)advanced 错误处理

    一.概述 原文地址:https://pro.ant.design/docs/error-cn 二.详细 2.1.页面级报错 2.1.1.应用场景 路由直接引导到报错页面,比如你输入的网址没有匹配到任何 ...

  8. ant design pro (十二)advanced UI 测试

    一.概述 原文地址:https://pro.ant.design/docs/ui-test-cn UI 测试是项目研发流程中的重要一环,有效的测试用例可以梳理业务需求,保证研发的质量和进度,让工程师可 ...

  9. ant design pro (十)advanced 图表

    一.概述 原文地址:https://pro.ant.design/docs/graph-cn Ant Design Pro 提供了由设计师精心设计抽象的图表类型,是在 BizCharts 图表库基础上 ...

  10. ant design pro (七)和服务端进行交互

    一.概述 原文地址:https://pro.ant.design/docs/server-cn Ant Design Pro 是一套基于 React 技术栈的单页面应用,我们提供的是前端代码和本地模拟 ...

随机推荐

  1. 2018CCPC 吉林现场赛 赛后总结

    一直以来都没有比赛完写总结的习惯,导致前面几次比赛都没有写过总结. 这是我写的第一场总结把,有时间有想法还记得细节的话再把前面几次比赛的总结给补上把. 热身赛: 热身赛的时候,写的比较急想着快点做出题 ...

  2. CF990C Bracket Sequences Concatenation Problem 思维 第五道 括号经典处理题目

     Bracket Sequences Concatenation Problem time limit per test 2 seconds memory limit per test 256 meg ...

  3. java-冒泡排序笔记

    //冒泡排序public class BubbleSort {    //    public static void main(String[] args) {//        // TODO 自 ...

  4. 【Offer】[67] 【把字符串转换成整数】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能 ...

  5. Linux OOM-killer(内存不足时kill高内存进程的策略)

    OOM_killer是Linux自我保护的方式,当内存不足时不至于出现太严重问题,有点壮士断腕的意味 在kernel 2.6,内存不足将唤醒oom_killer,挑出/proc/<pid> ...

  6. 基础知识:CSRF漏洞

    CSRF漏洞概述 CSRF漏洞是跨站请求伪造攻击,能够对攻击用户的增.删.改,不能攻击查.为什么呢?根据其原理,攻击者是发一个链接给用户,用户点击这个链接而执行危险的操作,信息并不会返回到攻击者的电脑 ...

  7. 5.cookie每个参数的意义和作用以及工作原理?

    cookie主要参数有: (1)expires 过期时间 (2)path cookie存放路径 (3)domain 域名 同域名下可访问 (4)Set-Cookie: name cookie名称

  8. Slickflow.NET 开源工作流引擎快速入门之三: 简单或分支流程代码编写示例

    前言:对于急切想了解引擎功能的开发人员,在下载版本后,就想尝试编写代码,完成一个流程的开发和测试.本文试图从请假流程,或分支模式来快速了解引擎代码的编写. 1. 创建或分支流程图形 或分支流程是常见的 ...

  9. 常用 JS 函数

    各种业务开发都离不开对数据的处理,然而遇到的很多数据都是不好处理的.这个时候就需要寻求搜索引擎的帮助.这种方法效率是非常低下的,而且根据作者的个性不能保证其对自己的口味.因此这篇文字包含了一份 JS ...

  10. mybatis #号与$号的区别

    区别: 在sql中当传入的参数是字符型,则用#号会带上单引号,不会引起sql注入: 在sql中当传入的参数是字符型,则用$号不会带上单引号,会引起sql注入: 使用范围: 当传入的参数用于查询条件,尽 ...