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. 【赛后总结+部分题解】2019中国大学生程序设计竞赛(CCPC) - 网络选拔赛

    赛后总结: T:今天状态一般,甚至有点疲惫.然后12点比赛开始,和队友开始看题,从最后往前面看,发现数学题公式看不懂.然后发现队友已经双开做1001和1006了,我看着1007有人A,开始做1007. ...

  2. 【牛客多校】Han Xin and His Troops

    题目: His majesty chatted with Han Xin about the capabilities of the generals. Each had their shortcom ...

  3. 逆序对 线段树&树状数组 (重制版)

    逆序对的定义:长度为n的数组a,求满足i<j时a[i]>a[j]条件的数对个数. 第一次接触这种问题的人可能是更先想到的是n^2去暴力数前面有几个比他大的数. int main() { i ...

  4. CodeForces 620D Professor GukiZ and Two Arrays 双指针

    Professor GukiZ and Two Arrays 题解: 将a数组都sort一遍之后, b数组也sort一遍之后. 可以观察得到 对于每一个ai来说, 整个数组bi是一个V型的. 并且对于 ...

  5. lightoj 1226 - One Unit Machine(dp+大组合数去摸)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1226 题解:由于这些任务完成是有先后的所以最后一个完成的肯定是最后一个任务的子 ...

  6. CF1005C Summarize to the Power of Two 暴力 map

    Summarize to the Power of Two time limit per test 3 seconds memory limit per test 256 megabytes inpu ...

  7. python3接口测试之webservice接口测试第三方库选择及新手问题

    一.使用python3做webervice接口测试的第三方库选择suds-jurko库,可以直接pip命令直接下载,也可以在pypi官网下载压缩包进行手动安装 二.安装好后,导入Client:from ...

  8. Nginx 反向代理基本框架

    全局配置指令:user nginx; 模块配置段 # 事件驱动模块,提供并发响应功能events{......}# http模块,提供web请求处理,可嵌套其他重要模块http{.......#ser ...

  9. MM52 历史库存及历史金额查询

    "表:TABLES:MSEG,LFA1,MARA,EKPO,EKKO,MARD,EKBE,EKET.********************************************* ...

  10. 本地代码上传至github

    一. 环境及工具 1.下载并安装git版本管理工具 到 http://git-scm.com/downloads 下载并安装git版本管理工具 2.Windows客户端 3.配置github账号密码及 ...