自创ant-design-pro组件
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组件的更多相关文章
- 【后台管理系统】—— Ant Design Pro组件使用(二)
一.关联表单项 - 动态增删输入框Input 封装子组件 class ParamsInputArray extends React.Component{ constructor(prop ...
- 【后台管理系统】—— Ant Design Pro组件使用(一)
一.搜索Search 搜索框 <Search placeholder="请输入关键字" defaultValue={kw && kw != 'nul ...
- Ant Design Pro路由传值
Ant Design Pro 路由传值 了解Ant Design Pro组件间通讯原理的小伙伴肯定都知道,两个页面之间可以通过Models进行传值,在以往的传值过程中,我都是直接将需要的值直接一股脑的 ...
- ant design pro 当中改变ant design 组件的样式和 数据管理
ant design pro 简介 官网简介 链接 https://pro.ant.design/docs/getting-started-cn 项目结构 https://github.com/ant ...
- 阿里开源项目之Ant Design Pro
本篇文章主要包含的内容有三个方面. 第一.Ant Design Pro简介; 第二.Ant Design Pro能做什么; 第三.初步使用; 我相信通过这三个方面的讲解能让你大概知道Ant Desig ...
- ant design pro (十四)advanced 使用 CLI 工具
一.概述 原文地址:https://pro.ant.design/docs/cli-cn 为了更好以及高效的开发效率,我们提供了配套的 ant-design-pro-cli 工具. pro cli 提 ...
- ant design pro (十三)advanced 错误处理
一.概述 原文地址:https://pro.ant.design/docs/error-cn 二.详细 2.1.页面级报错 2.1.1.应用场景 路由直接引导到报错页面,比如你输入的网址没有匹配到任何 ...
- ant design pro (十二)advanced UI 测试
一.概述 原文地址:https://pro.ant.design/docs/ui-test-cn UI 测试是项目研发流程中的重要一环,有效的测试用例可以梳理业务需求,保证研发的质量和进度,让工程师可 ...
- ant design pro (十)advanced 图表
一.概述 原文地址:https://pro.ant.design/docs/graph-cn Ant Design Pro 提供了由设计师精心设计抽象的图表类型,是在 BizCharts 图表库基础上 ...
- ant design pro (七)和服务端进行交互
一.概述 原文地址:https://pro.ant.design/docs/server-cn Ant Design Pro 是一套基于 React 技术栈的单页面应用,我们提供的是前端代码和本地模拟 ...
随机推荐
- CF - 1108 F MST Unification
题目传送门 题意:在一幅图中, 问需要使得多少条边加一,使得最小生成树只有一种方案. 题解:Kruskal, sort完之后,对于相通的一个边权w,我们可以分析出来有多少边是可以被放到图里面的,然后我 ...
- lightoj 1036 - A Refining Company(简单dp)
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1036 题解:设dp[i][j]表示处理到(i,j)点时的最大值然后转移显然是 ...
- codeforces 816 C. Karen and Game(模拟+思维)
题目链接:http://codeforces.com/contest/816/problem/C 题意:给出一个矩阵,问能否从都是0的情况下只将一整行+1或者一整列+1变形过来,如果可以输出需要步数最 ...
- codeforces 361 C. Levko and Array Recovery(暴力+思维)
题目链接:http://codeforces.com/contest/361/problem/C 题意:对一个数列有这么两个操作 1.(1,l,r,p)..将区间[l,r]所有数都加上p 2.(2,l ...
- Unsolved输入格式错误1022
https://pintia.cn/problem-sets/994805342720868352/problems/994805480801550336
- SpringBoot 2.0 + 阿里巴巴 Sentinel 动态限流实战
前言 在从0到1构建分布式秒杀系统和打造十万博文系统中,限流是不可缺少的一个环节,在系统能承受的范围内既能减少资源开销又能防御恶意攻击. 在前面的文章中,我们使用了开源工具包 Guava 提供的限流工 ...
- 计时器Chronometer
布局文件很简单 <Chronometer android:id="@+id/test" android:layout_width="wrap_content&quo ...
- jupyter lab(notebook)相关配置
安装的是Anaconda3(Python 3.6.4),自带的版本较低,这里升级版本conda update jupyterlab 一.配置jupyter lab(notebook)远程访问 1.1 ...
- 解决在Filter中读取Request中的流后,后续controller或restful接口中无法获取流的问题
首先我们来描述一下在开发中遇到的问题,场景如下: 比如我们要拦截所有请求,获取请求中的某个参数,进行相应的逻辑处理:比如我要获取所有请求中的公共参数 token,clientVersion等等:这个时 ...
- PTA A1014
A1014 Waiting in Line (30 分) 题目内容 Suppose a bank has N windows open for service. There is a yellow l ...