这个系统的搭建背景是这样的.有一个朋友想看到现有系统中的一些,用户数据,新闻数据,只需要看到,短期不需要增删改功能,让我搭建一个简单的后台系统给他看.接到任务作为一个有四年开发经验的人来说这也太简单了吧,开始干吧,最简单的办法是直接使用开源项目
https://github.com/PanJiaChen/vue-element-admin
<https://github.com/PanJiaChen/vue-element-admin>
 下载下来,把不要的路由去掉,新建几个表格路由,页面直接复制过来就用了.


这样算下来,整个系统搭建时间不会超过半天,而且这个开源框架我已经玩的很溜了,后期开发完全不费事.但是,这个方案被我拒绝了.为什么那?因为我想跳出舒适区.接受更大的挑战,目前和vue并驾齐驱的React项目也很流程,很多公司也在使用.于是乎,技术栈就是用React了.但是要从零搭建,时间上划不来,因为需要集成很多东西,基础建设就要耗费很长时间.于是乎在GitHub上一顿搜,Ok
找到了二个比较可靠的项目使用,一个是 ant-design-pro
<https://github.com/ant-design/ant-design-pro/> 另一个是antd-admin
<https://github.com/zuiidea/antd-admin> 二个项目大同小异, 使用的技术栈react
<https://github.com/facebook/react>,ant-design
<https://github.com/ant-design/ant-design>,dva <https://github.com/dvajs/dva>,
Mock <https://github.com/nuysoft/Mock>  基于 Antd UI 设计语言  虽然我对dva和ant-design
了解不深,但我还是准备挑战一下.不入虎穴焉得虎子.

  一开始我选择的是antd-admin <https://github.com/zuiidea/antd-admin>
 因为代码比较规范,UI也比较符合我的审美.开始做吧

 首先找到一个列表页,仔细阅读代码,弄清楚依赖关系,然后新建一个目录,把列表页的相关文件都拷贝进去, 配路由,设置权限.


但是在调取接口的时候,接口虽然调取了,但是页面没有刷新出来,怎么调试都不出来,急死了.最后只好需求同事的帮助,但是他们也很少有人用React.就这样过了一天,我决定先把问题放一下,
问题的答案肯定就在代码里,先休息一下,别被这个问题让自己的眼光太局限,导致看不到问题的本质.在这个问题还没有解决的情况下,我又开始了另一个项目 
ant-design-pro <https://github.com/ant-design/ant-design-pro/>
的尝试.因为我知道,那个页面没有显示数据的问题,我肯定会解决的,只是时间问题,当我解决了,肯定会觉得自己当时太笨了,后来的进展证明确实是这样.

  在数据不显示的问题上短暂停留下,我开始探索ant-design-pro
<https://github.com/ant-design/ant-design-pro/>

  这里我来说一下,当一个菜鸟接手一个新项目时遇到的迷茫和问题.


 首先项目开启我们会看到页面的URL,URL与我们的页面是一一对应的,意思就是我们根据URL可以再项目中准确地找到对应的页面,或页面入口.当然页面可能会一个主页面,多个子页面.这里忘记说一点,URL对应页面
这种对应关系的配置,叫做路由.

看到URL,就能找到路由,就能找到页面, 找到页面就完成了项目熟悉的第一步, 到了这一步,你就能自己写个静态页面,自己配个路由就能在浏览器看到了.
是不是很简单.这是大致的思路.不过有的框架有权限拦截,新的页面路由可能需要给登录的人赋权限才能出现. 等下我会以具体页面案例来做个演示.


第一步已经学会了,接下来就是进入到页面内,看看页面的数据是怎么流转的,事件,参数是怎么配置的.这一块是比较难的,也是熟悉前端项目的核心知识点.敲重点,重点,重点
一般一个页面,都会有初始化函数,
比如一个vue组件会在mounted状态下调取获取数据的接口,来渲染页面.React会在componentDidMount生命周期调取获取数据的接口.
每个页面或组件都有可能是两个或更多个组件,组合而来的,而组件的参数也是错综复杂,组件的表现,事件都是有这些参数控制的.除了简单理解这些参数,还需要理解这些组件是怎么组合起来的.

说也说了够多的 下面我就用一个列表页来给你看一下 我是怎么了解一个前端项目和开发的

我以ant-design-pro的查询表格页面为例子



我们拿着/list/table-list这个路由去项目中搜索 

打开这个文件 



很明显这个文件是路由管理  这里清楚的写着 /list/table-list路由指向文件../routes/List/TableList

其中代码中的
dynamicWrapper(app, ['rule'], ()
我们暂时不需要去理解他的意思,因为我们的第一步是根据路由找到对应的页面. 而不是去理解每一行代码.

打开../routes/List/TableList我们看到



果然是我们要寻找的页面, 改一二个文字 刷新一下页面,果然改变了.好开心.第一步就这样完了.

必须要提的全局搜索是一个非常很好的技能,大家一定要学会.另外 搜素路由的时候,有的路由是分开写的,比如路由/list/table-list 是有/list
和/table-list 直接搜/list/table-list搜不到,这个时候你就要去尝试单个搜索了,交叉比对,或者,找像路由配合的目录
这是一个简单实用的方法.走到这一步,你就可以自己去创建一个页面,配一个路由看看了.

接下来说一下进入页面内部改如何快速理解页面大致结构
import React, { PureComponent, Fragment } from 'react'; import { connect }
from 'dva'; import moment from 'moment'; import { Row, Col, Card, Form, Input,
Select, Icon, Button, Dropdown, Menu, InputNumber, DatePicker, Modal, message,
Badge, Divider, } from 'antd'; import StandardTable from
'components/StandardTable'; import PageHeaderLayout from
'../../layouts/PageHeaderLayout'; import styles from './TableList.less'; const
FormItem = Form.Item; const { Option } = Select; const getValue = obj =>
Object.keys(obj) .map(key => obj[key]) .join(','); const statusMap =
['default', 'processing', 'success', 'error']; const status = ['关闭', '运行中',
'已上线', '异常']; const CreateForm = Form.create()(props => { const { modalVisible,
form, handleAdd, handleModalVisible } = props; const okHandle = () => {
form.validateFields((err, fieldsValue) => { if (err) return;
form.resetFields(); handleAdd(fieldsValue); }); }; return ( <Modal title="新建规则"
visible={modalVisible} onOk={okHandle} onCancel={() => handleModalVisible()} >
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="描述">
{form.getFieldDecorator('desc', { rules: [{ required: true, message: 'Please
input some description...' }], })(<Input placeholder="请输入" />)} </FormItem>
</Modal> ); }); @connect(({ rule, loading }) => ({ rule, loading:
loading.models.rule, })) @Form.create() export default class TableList extends
PureComponent { state = { modalVisible: false, expandForm: false, selectedRows:
[], formValues: {}, }; componentDidMount() { const { dispatch } = this.props;
dispatch({ type: 'rule/fetch', }); } handleStandardTableChange = (pagination,
filtersArg, sorter) => { const { dispatch } = this.props; const { formValues }
= this.state; const filters = Object.keys(filtersArg).reduce((obj, key) => {
const newObj = { ...obj }; newObj[key] = getValue(filtersArg[key]); return
newObj; }, {}); const params = { currentPage: pagination.current, pageSize:
pagination.pageSize, ...formValues, ...filters, }; if (sorter.field) {
params.sorter = `${sorter.field}_${sorter.order}`; } dispatch({ type:
'rule/fetch', payload: params, }); }; handleFormReset = () => { const { form,
dispatch } = this.props; form.resetFields(); this.setState({ formValues: {},
}); dispatch({ type: 'rule/fetch', payload: {}, }); }; toggleForm = () => {
const { expandForm } = this.state; this.setState({ expandForm: !expandForm, });
}; handleMenuClick = e => { const { dispatch } = this.props; const {
selectedRows } = this.state; if (!selectedRows) return; switch (e.key) { case
'remove': dispatch({ type: 'rule/remove', payload: { no: selectedRows.map(row
=> row.no).join(','), }, callback: () => { this.setState({ selectedRows: [],
}); }, }); break; default: break; } }; handleSelectRows = rows => {
this.setState({ selectedRows: rows, }); }; handleSearch = e => {
e.preventDefault(); const { dispatch, form } = this.props;
form.validateFields((err, fieldsValue) => { if (err) return; const values = {
...fieldsValue, updatedAt: fieldsValue.updatedAt &&
fieldsValue.updatedAt.valueOf(), }; this.setState({ formValues: values, });
dispatch({ type: 'rule/fetch', payload: values, }); }); }; handleModalVisible =
flag => { this.setState({ modalVisible: !!flag, }); }; handleAdd = fields => {
const { dispatch } = this.props; dispatch({ type: 'rule/add', payload: {
description: fields.desc, }, }); message.success('添加成功'); this.setState({
modalVisible: false, }); }; renderSimpleForm() { const { form } = this.props;
const { getFieldDecorator } = form; return ( <Form onSubmit={this.handleSearch}
layout="inline"> <Row gutter={{ md: 8, lg: 24, xl: 48 }}> <Col md={8} sm={24}>
<FormItem label="规则编号"> {getFieldDecorator('no')(<Input placeholder="请输入" />)}
</FormItem> </Col> <Col md={8} sm={24}> <FormItem label="使用状态">
{getFieldDecorator('status')( <Select placeholder="请选择" style={{ width: '100%'
}}> <Option value="0">关闭</Option> <Option value="1">运行中</Option> </Select> )}
</FormItem> </Col> <Col md={8} sm={24}> <span className={styles.submitButtons}>
<Button type="primary" htmlType="submit"> 查询 </Button> <Button style={{
marginLeft: 8 }} onClick={this.handleFormReset}> 重置 </Button> <a style={{
marginLeft: 8 }} onClick={this.toggleForm}> 展开 <Icon type="down" /> </a>
</span> </Col> </Row> </Form> ); } renderAdvancedForm() { const { form } =
this.props; const { getFieldDecorator } = form; return ( <Form
onSubmit={this.handleSearch} layout="inline"> <Row gutter={{ md: 8, lg: 24, xl:
48 }}> <Col md={8} sm={24}> <FormItem label="规则编号">
{getFieldDecorator('no')(<Input placeholder="请输入" />)} </FormItem> </Col> <Col
md={8} sm={24}> <FormItem label="使用状态"> {getFieldDecorator('status')( <Select
placeholder="请选择" style={{ width: '100%' }}> <Option value="0">关闭</Option>
<Option value="1">运行中</Option> </Select> )} </FormItem> </Col> <Col md={8}
sm={24}> <FormItem label="调用次数"> {getFieldDecorator('number')(<InputNumber
style={{ width: '100%' }} />)} </FormItem> </Col> </Row> <Row gutter={{ md: 8,
lg: 24, xl: 48 }}> <Col md={8} sm={24}> <FormItem label="更新日期">
{getFieldDecorator('date')( <DatePicker style={{ width: '100%' }}
placeholder="请输入更新日期" /> )} </FormItem> </Col> <Col md={8} sm={24}> <FormItem
label="使用状态"> {getFieldDecorator('status3')( <Select placeholder="请选择" style={{
width: '100%' }}> <Option value="0">关闭</Option> <Option value="1">运行中</Option>
</Select> )} </FormItem> </Col> <Col md={8} sm={24}> <FormItem label="使用状态">
{getFieldDecorator('status4')( <Select placeholder="请选择" style={{ width: '100%'
}}> <Option value="0">关闭</Option> <Option value="1">运行中</Option> </Select> )}
</FormItem> </Col> </Row> <div style={{ overflow: 'hidden' }}> <div style={{
float: 'right', marginBottom: 24 }}> <Button type="primary" htmlType="submit">
查询 </Button> <Button style={{ marginLeft: 8 }} onClick={this.handleFormReset}>
重置 </Button> <a style={{ marginLeft: 8 }} onClick={this.toggleForm}> 收起 <Icon
type="up" /> </a> </div> </div> </Form> ); } renderForm() { const { expandForm
} = this.state; return expandForm ? this.renderAdvancedForm() :
this.renderSimpleForm(); } render() { const { rule: { data }, loading, } =
this.props; const { selectedRows, modalVisible } = this.state; const columns =
[ { title: '规则编号', dataIndex: 'no', }, { title: '描述', dataIndex: 'description',
}, { title: '服务调用次数', dataIndex: 'callNo', sorter: true, align: 'right',
render: val => `${val} 万`, // mark to display a total number needTotal: true,
}, { title: '状态', dataIndex: 'status', filters: [ { text: status[0], value: 0,
}, { text: status[1], value: 1, }, { text: status[2], value: 2, }, { text:
status[3], value: 3, }, ], onFilter: (value, record) =>
record.status.toString() === value, render(val) { return <Badge
status={statusMap[val]} text={status[val]} />; }, }, { title: '更新时间',
dataIndex: 'updatedAt', sorter: true, render: val =>
<span>{moment(val).format('YYYY-MM-DD HH:mm:ss')}</span>, }, { title: '操作',
render: () => ( <Fragment> <a href="">配置</a> <Divider type="vertical" /> <a
href="">订阅警报</a> </Fragment> ), }, ]; const menu = ( <Menu
onClick={this.handleMenuClick} selectedKeys={[]}> <Menu.Item
key="remove">删除</Menu.Item> <Menu.Item key="approval">批量审批</Menu.Item> </Menu>
); const parentMethods = { handleAdd: this.handleAdd, handleModalVisible:
this.handleModalVisible, }; return ( <PageHeaderLayout title="查询表格"> <Card
bordered={false}> <div className={styles.tableList}> <div
className={styles.tableListForm}>{this.renderForm()}</div> <div
className={styles.tableListOperator}> <Button icon="plus" type="primary"
onClick={() => this.handleModalVisible(true)}> 新建 </Button>
{selectedRows.length > 0 && ( <span> <Button>批量操作</Button> <Dropdown
overlay={menu}> <Button> 更多操作 <Icon type="down" /> </Button> </Dropdown>
</span> )} </div> <StandardTable selectedRows={selectedRows} loading={loading}
data={data} columns={columns} onSelectRow={this.handleSelectRows}
onChange={this.handleStandardTableChange} /> </div> </Card> <CreateForm
{...parentMethods} modalVisible={modalVisible} /> </PageHeaderLayout> ); } }
 

以这个页面为例

第一次阅读代码我们一定要按照从上到下的顺序阅读,记住 是第一次.第一次第一次

首先这个文件引入了几个组件 React dva moment antd  .....

我们要对这个库或组件有个大致印象,比如我们要在页面修改antd 的Dropdown组件,就要去antd官文看看有那些参数可以调整.

其他组件和工具库都是这样.假如你把页面头部的import 的东西有了大致了解,就继续往下看.

页面有const 定义了一个方法,或一系列对象,这个对象有的是作为组件的参数 有的本身就是小子组件

 但我们看到这段代码时就要特别注意了
componentDidMount() { const { dispatch } = this.props; dispatch({ type:
'rule/fetch', }); }
在React组件的componentDidMount生命周期时 执行了
dispatch({ type: 'rule/fetch', });
获取你不知道dva 或许你根本看不懂这段代码,但是你可以想象他到底是什么意思.有什么作用. 或者你直接删掉这段代码,看看页面有什么变化.
了解代码效果最简单最明了的方法是 直接删掉,看看报什么错,或有什么变化...O(∩_∩)O哈哈~虽然不是什么好方法,但是简单易用.到这里 你大概知道
这段代码大概就是去调取接口获取数据渲染到页面的.这种写法可能与我们平时写的不一样

我们平时调取接口大概是这样的
copyrightTypeList().then(res => { if (res.data.code === 0) {
this.caseTypeList = res.data.data } })
少年不要迷茫了,要接受改变.学习新的知识吧,跳出你的舒适区.

dispatch({ type: 'rule/fetch', }); 这段代码的关键字是rule/fetch
要先在页面仔细搜索关于rule和fetch相关的代码.

在搜素了很久我终于好到 rule是在那里



......文章到这里就吿一段落了 剩余的就好理解了

属性一个项目还有一个方法就是打开项目的package.json 将里面的包 挨个查一遍,了解每个包的作用,用法.这也不失为一种好的快速上手的方法

谢谢阅读.如果觉得对你有帮助请记得点赞或收藏.欢迎留言讨论.谢谢.

 

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信