刚入职一个星期,因为公司的前端框架是用React的,而我以前都是用Vue的,所以又要从头开始学了,听很多人说React上手挺难的,辛亏有Vue的开发经验,看了两天就开始上手公司的项目了,公司主要做的是偏向后台管理系统,所以就采用Ant Design Pro这个框架(蚂蚁金服做的),又是一番挣扎啊。这篇文章就当是对这个星期挣扎的总结吧。

安装

有两种方法:

  1. 直接克隆它的模板
$ git clone --depth=1 https://github.com/ant-design/ant-design-pro.git my-project

  1. 通过脚手架安装(ant-design-pro-cli)
$ npm install ant-design-pro-cli -g //安装全局的脚手架

$ pro new 项目名字 (my-project) //初始化项目 

模板下载下载来了然后要下载它的依赖

$ cd my-project (项目的名字)  //进入目录

$ npm i (install的缩写)     //安装项目依赖

温馨提示:由于国内原因npm下载依赖会有点慢, 大家可以把npm的源切换到淘宝的镜像源或者用cnpm来安装依赖

切换源(运行下面的命令):

$ npm config set registry http://registry.npm.taobao.org/ //切换淘宝的源

$ npm config set registry https://registry.npmjs.org/   //原来的源

cnpm(运行下面的命令):

$ npm install -g cnpm --registry=https://registry.npm.taobao.org

安装完成,现在开始进入开发模式,嘿嘿!!!

第一步肯定是要看目录啊是吧?(应该是)

Ant Design Pro目录结构

看到这么多目录,如果是没有这方面的架构的开发经验,肯定会有无从下手的感觉,所以下面我就把我上手这个框架的一些思路写下(希望这篇文章能让大家少踩点坑嘿嘿)

上手之前最好有以下的知识点: React、Dva、Webpack、ES6、Less等等。

小提示:开始之前先来配置下webpack的alias属性吧,这个是配置路径的别名的
打开根目录下面的.webpackrc文件

alias: { components: path.resolve(__dirname, 'src/components/'), src: path.resolve(__dirname, 'src'), utils: path.resolve(__dirname, 'utils') } //保存之后记得重启下项目喔 然后就可以在项目里面进行愉快的开发了比如: 要引入一个components的组件,不管你在那个目录直接 import * from 'components/对应的组件' 不用在各种../了,是不是很方便。

接下来就是正题了

1.主入口文件index.js:

比较重要的

import './index.less'; //引入全局的样式 // 1. 初始化 const app = dva({ history: createHistory(), }); // 2. 注册全局的插件 app.use(createLoading()); // 3. 注册全局的模型 app.model(require('./models/global').default); // 4. 注入路由配置 app.router(require('./router').default); // 5.启动 #root 是index.ejs 里面的一个根节点id,可以更改 app.start('#root');

2.布局(layout)

And DesigR Pro 提供了3种布局

BlankLayout 这个是空白的布局

UserLayout 这个是登录的界面的布局,如下图:

UserLayout布局

PageHeaderLayout 这个是后台界面的经典布局,头部导航,左侧固定导航,右边是内容,如下图:

PageHeaderLayout布局

这个我想着重说下怎么新建一个自己想要的布局:
1.首先在src/layout里面新建一个NewLayout.js布局,这里说下我要的布局:左侧固定导航,右侧直接根据导航显示对应的页面。

NewLayout.js

import React, { Component } from 'react'; import { Row, Col } from 'antd' import { Route, Switch } from 'dva/router'; import { getRoutes } from 'src/utils/utils'; export default class NewLayout extends Component { constructor(props){ super(props) } render(){ const { routerData, match } = this.props; const routes = getRoutes(match.path, routerData); return ( <Row> <Col span="4" style={{background: "#000", position: 'fixed',color: '#fff', height: '100%'}}>左侧固定导航</Col> <Col span="20" offset={4}> {/* 下面代码的意思是根据路由来渲染对应的组件 */} <Switch> {routes.map(item => { return (<Route key={item.key} path={item.path} exact={item.exact} component={item.component} />); })} </Switch> </Col> </Row> ) } }

然后在根路由中增加这一组新模板src/router.js

function RouterConfig({ history, app }) { const routerData = getRouterData(app); const BaseLayout = routerData['/'].component; const NewLayout = routerData['/new'].component; //新添加的 return ( <LocaleProvider locale={zhCN}> <ConnectedRouter history={history}> <Switch> <Route path="/" render={props => <BaseLayout {...props} />} /> <Route path="/new" render={props => <NewLayout {...props} />} /> //新添加的 </Switch> </ConnectedRouter> </LocaleProvider> ); }

再然后去配置路由src/common/router.js

//只需改routerConfig变量, ['new'] 这个是加载对应的Model,稍后会说。 const routerConfig = { ... '/new': { component: dynamicWrapper(app, ['new'], () => import('../layouts/NewLayout')) }, '/new/a': { component: dynamicWrapper(app, ['new'], () => import('../routes/new/A')) }, '/new/b': { component: dynamicWrapper(app, ['new'], () => import('../routes/new/b')) } };

自此,新增一个布局就好了,可以在浏览器访问http://localhost/#/new就会显示我们新建的布局了,访问http://localhost/#/new/a右侧的内容就显示a页面的内容了,http://localhost/#/new/b 右侧的内容就显示b页面的内容。

3.模型(Model)

因为我们在上面的路由配置里面使用了new这个model,下面我们就来添加这个model。在src/models/新建一个new.js

一个model主要有5个参数: namespace:String(命名空间,必须在所有模型中保证唯一)、state:Object(model初始化的数据)、effects:Object(所有的异步操作都在这里操作,这里不能改变state,但是可以获取state)、reducers:Object(所有的同步操作,也是唯一可以改变state的地方,要返回一个Object,会覆盖state)、subscriptions:Object(订阅一个数据源)

new.js

import { getUserList } from '../services/api' export default { namespace: 'new', state: { userList: {}, //用户列表 count: 0 //计数 }, effects: { /** * getConfig * @param {payload} payload * @param {call, put, select} param1 * 因为都是异步操作,可以用ES6的Generator或者用ES7的async await */ *getConfig({payload}, {call, put, select}){ /** 参数说明: payload: 传过来的参数 call: 执行一个异步的函数,比如请求服务器的接口,返回一个Promise put: 执行一个action(操作) select: 获取state,但是不能更改 */ // 来,demo走一波 //从服务器获取用户列表的数据 let res = yield call(getUserList, {page: 1}); // 然后更新state的数据,这时候就用到put了 yield put({ type: 'updateUser', //执行自身模块的action不用加命名空间 payload: res //把获取来的列表传过去 }); } }, reducers: { /** * 更新学生的数据 * @param {*} state * @param {*} action */ updateUser(state, action){ // 这里可以用解构的方式来合并state return { ...state, ...action }; }, /** * 更新计数器 */ increment(state){ return { ...state, count: state.count+1 } } }, subscriptions: { /** * 每秒更新state的count */ interval() { return setInterval(()=>{ dispatch({ type: 'increment' }) }, 1000) } }, };

4.路由(router)

路由在新增的页面也说了,这里在补充下路由的配置和组件、model的关联

路由配置src/common/router.js

routerConfig = { '/': { component: dynamicWrapper(app, ['new'], () => import('../layouts/NewLayout')), name: '首页' //这个是额外的参数,如果用了PageHeader这个组件,可以生成面包屑导航 } } dynamicWrapper //这个函数接收3个参数,1.挂载的对象 2.路由所需要的model,可以多个,前提你已经在src/models里面新建了对应的模型了,名字和文件名字一样就行 3.路由所需要的组价,我们把页面的组件放到src/routes里面

组件、model的关联

//先配置下路由 routerConfig = { '/user': { component: dynamicWrapper(app, ['new'], () => import('../routes/User/List')), } } //再src/routes/User 添加对应的组件 List(列表), 组件代码如下: import React, { Component } from 'react'; import { connect } from 'dva'; // 使用connect注入到props里面去,中间不能有东西,除非同样是装饰器。 @connect(({new, global}) => ({ userList: new.userList })) export default class UserPage extends Component { constructor(props){ super(props); console.log(props.userList) //就能获取到new模型里面的值了 //在组件想要更改model里面的值可以这样子玩: //用了connect会自动在props注入dispatch props.dispatch({ type: 'new/updateUser', //命名空间 + 要执行的action payload: { //要更改的数据 } }) } render() { return ( <div>用户列表</div> ) } }

services 和 utils 在这里就不说了,最后在说下,如果用了PageHeaderLayout布局,怎么添加一个新的菜单。

打开src/common/menu.js

//你想插入的配置插入下面的代码结构就行 { name: '用户管理', //菜单的名字 icon: 'user', //菜单的图标 path: 'user', //在路由配置的路径 children: [ //二级菜单 { name: '用户列表', path: 'list', } ] }

然后在src/common/router.jsrouterConfig变量里面添加相应的路由配置就行了。

{ ... '/user': { //user的根路由代码可以和新增布局NewLayout显示右侧内容代码一样,一般都会这样子搞 component: dynamicWrapper(app, ['user'], () => import('../routes/User')), }, '/user/list': { component: dynamicWrapper(app, ['user'], () => import('../routes/User/List')), } }

就写到这里吧,刚学React一个星期左右,这篇文章写了我两天,总结出一些我踩的一些坑,这篇文章权当是一篇学习React的笔记吧,各位大神有看到不足之处的,可以在评论区留言,感激不尽!!!

(逃~)