搭建Ant-Design-Pro项目


最近公司项目使用了ant design pro,从没接触过react的我只能趁着周末学习熟悉,赶紧上手。(都是泪。。)说到ant design pro,得先了解一下ant design是个什么东西?ant design蚂蚁金服基于react打造的一个服务于企业级产品的UI框架。而ant design pro呢?就是基于Ant Design这个框架搭建的中后台管理控制台的脚手架 。连登陆界面主界面布局都写好了,只需要在里面写业务相关的页面就可以了,节省不少人力。它秉承 Ant Design 的设计价值观,致力于在设计规范和基础组件的基础上,继续向上构建,提炼出典型模板/业务组件/配套设计资源,进一步提升企业级中后台产品设计研发过程中的『用户』和『设计者』的体验。使用antd-pro 之前,开发的同学们最好了解 ES2015+、React、UmiJS、dva、g2 、 antd以及React Router v4的基础知识,这将为你的开发工作提供必要的基础。需要学习的东西挺多,上手门槛比VUE高了一些。这里主要记录本人从零搭建ant design pro的过程,以及常用的语法

项目搭建

首先,找个地方建个空目录,然后使用 npm create umi 脚手架,创建模板:

选择第一项:ant-design-pro。然后回车

为了简单起见,选择JavaScript创建项目,然后一路回车。到下面这个步骤项目就已经初始化好了

使用webstorm打开刚刚创建的工程,可以看到目录结构如下

├── config  # umi 配置,包含路由,构建等配置
│  ├── config  # 配置文件:包含路由、样式、proxy等
│  ├── defaultSettings # 默认设置:包括标题title、navTheme等
│  ├── plugin.config # webpack的Plugin配置
│  ├── themePluginConfig # 风格主题的配置
├── mock  # 本地模拟数据
├── public
│  └── favicon.png # Favicon
├── src
│  ├── assets  # 本地静态资源
│  ├── components  # 业务通用组件
│      ├...
│      ├── GlobalHeader  # 基础布局的头部
│          ├── AvatarDropdown  # 用户头像下拉菜单
│          ├── NoticeIconView  # 通知图标和通知消息视图
│          ├── plugin.config # webpack的Plugin配置
│          ├── RightContent  # 基础布局的头部核心:包含搜索、头像、语言选择
│  ├── e2e # 集成测试用例
│  ├── layouts # 通用布局
│  ├── models  # 全局 dva model
│  ├── pages # 业务页面入口和常用模板
│  ├── services  # 后台接口服务
│  ├── utils # 工具库
│  ├── locales # 国际化资源
│  ├── global.less # 全局样式
│  └── global.ts # 全局 JS
├── tests # 测试工具
├── README.md
├── package.json
└── ... # 其他

然后进入目录,执行 npm install 下载前端依赖包,在下载依赖过程中可能会失败,显示会是权限问题,其实就是包下载不下来,报错如下

而一次出错之后,一般人都会再次npm install ,而npm install命令并不会主动清除上次安装的包,而你上次安装的包又不完整,包与包之间又有依赖关系,结果自然再次出错。所以,要想解决这个问题,就应该清除上次安装的包,想要彻底清除则一般需要以下3步,删除node modules中的全部文件。然后执行:npm cache clean --force 命令,npm可执行命令如下

npm start # 运行这个脚本会启动服务,自动打开默认浏览器展示你的页面。当你重新编辑代码后,页面还会自动刷新。
npm run build # 运行这个脚本将会编译你的项目,你可以在项目中的 dist 目录中找到编译后的文件用于部署。
npm run lint # 通过这个脚本来查看你的代码有哪些问题
npm test # 这个脚本会执行一系列测试,包括 e2e 测试。
npm run i18n-remove # 这个脚本将会尝试删除项目中所有的 i18n 代码,对于复杂的运行时代码,表现并不好,慎用。

执行 npm start,启动成功后可看到主界面

到此,ant design pro项目就搭建好了。下面介绍一下JSX语法吧,这是React官方推荐的模板语法,与VUE使用模板的方式差别还是挺大的。不过本人在使用了Vue和React后,觉得Vue的模板语法使用更加顺手,基本上符合Html的语法,上手更快。看个人习惯吧

JSX模板语法

简单来说,在JS中书写HTML语法(不是简单在JS中写HTML字符串),就可称之为JSX语法。JSX就是Javascript和XML结合的一种格式。React发明了JSX,利用HTML语法来创建虚拟DOM。当遇到<,JSX就当HTML解析,遇到{就当JavaScript解析。JS语法与JSX语法的区别。在普通的JS语法中,如果想渲染一段html文本的话,我们需要这么做。如下:

var child1 = React.createElement('li', null, 'First Text Content');
var child2 = React.createElement('li', null, 'Second Text Content');
var root = React.createElement('ul', { className: 'my-list' }, child1, child2);

等价于(JSX写法)

var root =(
  <ul className="my-list">
    <li>First Text Content</li>
    <li>Second Text Content</li>
  </ul>
);

后者将XML语法直接加入JS中,通过代码而非模板来高效的定义界面。之后JSX通过翻译器转换为纯JS再由浏览器执行。在实际开发中,JSX在产品打包阶段都已经编译成纯JavaScript,JSX的语法不会带来任何性能影响。另外,由于JSX只是一种语法,因此JavaScript的关键字class, for等也不能出现在XML中,而要如例子中所示,使用className, htmlFor代替,这和原生DOM在JavaScript中的创建也是一致的。JSX只是创建虚拟DOM的一种语法格式而已,除了用JSX,我们也可以用JS代码来创建虚拟DOM。

JSX的基本使用

要使用 JSX 则必须要引入React,React的每一个组件都有render函数,render函数返回的就是JSX渲染的内容,JSX的基本使用个HTML标签没有什么区别。

import React, { Component } from 'react';

class App extends Component {
  render() {
    return (
        <div>Hello word!</div>  
    );
  }
}
export default App;

JSX占位符:Fragement

在JSX中返回的内容都必须包含在一个大的标签内,所以我们不得不在最外边套一层div,如果我们不希望页面渲染这层div的话就需要使用占位符-Fragement在JSX中返回的内容都必须包含在一个大的标签内,所以我们不得不在最外边套一层div,如果我们不希望页面渲染这层div的话就需要使用占位符-Fragement

import React, { Component, Fragement} from 'react';

class App extends Component {
  render() {
    return (
        <Fragement>
            <div>Hello word!</div>
            <div>Hello React!</div>
        </Fragement>  
    );
  }
}

JSX中绑定事件

SX让事件直接绑定在元素上。

<button onClick={this.checkAndSubmit.bind(this)}>Submit</button>

和原生HTML定义事件的唯一区别就是JSX采用驼峰写法来描述事件名称,大括号中仍然是标准的JavaScript表达式,返回一个事件处理函数。React并不会真正的绑定事件到每一个具体的元素上,而是采用事件代理的模式:在根节点document上为每种事件添加唯一的Listener,然后通过事件的target找到真实的触发元素。这样从触发元素到顶层节点之间的所有节点如果有绑定这个事件,React都会触发对应的事件处理函数。这就是所谓的React模拟事件系统。尽管整个事件系统由React管理,但是其API和使用方法与原生事件一致。

JSX中使用样式

在JSX中使用样式和真实的样式也很类似,通过style属性来定义,但和真实DOM不同的是,属性值不能是字符串而必须为对象。例如:

<div style={{color: '#ff0000', fontSize: '14px'}}>Hello World.</div>

或者

var style = {
  color: '#ff0000',
  fontSize: '14px'
};

var node = <div style={style}>HelloWorld.</div>;

要明确记住,{}里面是JS代码,这里传进去的是标准的JS对象。在JSX中可以使用所有的的样式,基本上属性名的转换规范就是将其写成驼峰写法,例如“background-color”变为“backgroundColor”, “font-size”变为“fontSize”,这和标准的JavaScript操作DOM样式的API是一致的。

父组件向子组件传值

父组件Comment.js

import React from "react"
import ComentList from "./ComentList"

class Comment extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            arr: [{
                "userName": "fangMing", "text": "123333", "result": true
            }, {
                "userName": "zhangSan", "text": "345555", "result": false
            }, {
                "userName": "liSi", "text": "567777", "result": true
            }, {
                "userName": "wangWu", "text": "789999", "result": true
            },]
        }
    }





    render() {
        return (
            <div>
                <ComentList arr={this.state.arr}> //这里把state里面的arr传递到子组件,等号左边的arr就是形参名,在子组件中取参数也是取arr
                </ComentList>

            </div>

        )
    }
}

export default Comment;

子组件ComentList.js

import React from "react"

class ComentList extends React.Component {
    constructor(props) {
        super(props);

    }
    render() {
        return (
            <div className="list">
                <ul>
                    {
                        this.props.arr.map(item => { //这个地方通过this.props.arr接收到父组件传过来的arr,然后在{}里面进行js的循环
                            return (
                                <li key={item.userName}>
                                    {item.userName} 评论是:{item.text}
                                </li>
                            )
                        })
                    }
                </ul>

            </div>
        )
    }
}

export default ComentList;

子组件向父组件传值

父组件Comment.js

import React from "react"
import ComentList from "./ComentList"

class Comment extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            parentText: "this is parent text",

            arr: [{
                "userName": "fangMing", "text": "123333", "result": true
            }, {
                "userName": "zhangSan", "text": "345555", "result": false
            }, {
                "userName": "liSi", "text": "567777", "result": true
            }, {
                "userName": "wangWu", "text": "789999", "result": true
            },]
        }
    }

    fn(data) {
        this.setState({
            parentText: data //把父组件中的parentText替换为子组件传递的值
        },() =>{
           console.log(this.state.parentText);//setState是异步操作,但是我们可以在它的回调函数里面进行操作
        });

    }



    render() {
        return (
            <div>
                //通过绑定事件进行值的运算,这个地方一定要记得.bind(this),不然会报错,切记切记,因为通过事件传递的时候this的指向已经改变
                <ComentList arr={this.state.arr} pfn={this.fn.bind(this)}>
                </ComentList>
                <p>
                    text is {this.state.parentText}
                </p>

            </div>

        )
    }
}

export default Comment; 

子组件ComentList.js

import React from "react"

class ComentList extends React.Component {
    constructor(props) {
        super(props);
        this.state = ({
            childText: "this is child text"
        })

    }
    clickFun(text) {
        this.props.pfn(text)//这个地方把值传递给了props的事件当中
    }
    render() {
        return (
            <div className="list">
                <ul>
                    {
                        this.props.arr.map(item => {
                            return (
                                <li key={item.userName}>
                                    {item.userName} 评论是:{item.text}
                                </li>
                            )
                        })
                    }
                </ul>
                //通过事件进行传值,如果想得到event,可以在参数最后加一个event,这个地方还是要强调,this,this,this
                <button onClick={this.clickFun.bind(this, this.state.childText)}>
                    click me
                </button>
            </div>
        )
    }
}

export default ComentList;

最后想说一点,如果嵌套的父子组件很深好几层,这个时候我想你应该考虑用状态管理工具redux了


Author: 顺坚
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source 顺坚 !
评论
 Previous
amr文件转mp3格式 amr文件转mp3格式
由于公司业务需求,需要做录音播放功能,简单来说就是业务员跟客户的通话记录会落地保存,然后需要用H5实现录音播放,但是录音文件保存的是amr格式,H5的audio标签不支持amr格式,需要把amr格式转mp3格式。于是去查了查相关格式转换的资
2020-03-17
Next 
Echarts图表各种参数详解 Echarts图表各种参数详解
公司做项目需要报表统计,用到Echarts。但是UI给出的风格和Echarts官方的风格差别有点大,因此需要自己去调整报表的风格样式,官方文档非常详细。但是每次都要去不同的菜单下去查看文档也很麻烦,在使用过程中个人对报表的统计参数做了一些总
2020-03-12
  TOC