React加Dva搭建前端项目


本文记录一下使用React+Antd从零开始搭建一个前端项目,Antd官方有一套完整成熟的前端项目集成了包括Antd,Dva,Redux等等。但是集成的东西太多太繁杂,以至于很难搞清楚它们的配置和使用。故本文从零搭建

环境准备

关于环境准备不是本文重点,假定已对Node环境,ES6语法,NPM,Weback等熟悉和使用

React搭建

  1. 使用create-react-app快速初始化 React 工程

    npx create-react-app my-app
    cd my-app
    npm start

    Create React App 是一个官方支持的创建 React 单页应用程序的方法。它提供了一个零配置的现代构建设置。

  2. 引入 antd ui 依赖

    npm install antd
    
    yarn add antd

    依赖导入成功后,需要在index.js中引入Antd的样式

    import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'

    推荐使用 npm 或 yarn 的方式进行安装,如果你的网络环境不佳,推荐使用 cnpm

  3. 引入 react-router 路由

    npm install react-router-dom

    react-router-dom其实就是react-router 4.0,与之前的3.0有什么区别呢?react-router被一分为三。react-routerreact-router-domreact-router-nativereact-router实现了路由的核心的路由组件和函数。而react-router-domreact-router-native都是基于react-router,提供了特定的环境的组件。

    所以我们使用npm安装依赖的时候,只需要安装相应环境下的库即可,不用再显式安装react-router。基于浏览器环境的开发,只需要安装react-router-dom;基于react-native环境的开发,只需要安装react-router-nativenpm会自动解析react-router-dom包中package.json的依赖并安装。

到此使用React搭建一个前端项目就完成了,使用 Create React App 官方脚手架创建项目时,默认首页是一个官方的demo页面,所以会生成一些我们自己开发时用不到的文件,我们可以删除它。默认项目目录如下

 |--node_modules
 |--package.json
 |--public
 |  |--favicon.ico
 |  |--index.html
 |  |--logo192.png              // 删除
 |  |--logo512.png              // 删除
 |  |--manifest.json            // 删除
 |  |--robots.txt               // 删除
 |--README.md
 |--src
 |  |--App.css                  // 删除
 |  |--App.js
 |  |--App.test.js              // 删除
 |  |--index.css                // 删除
 |  |--index.js                 
 |  |--logo.svg                 // 删除
 |  |--reportWebVitals.js       
 |  |--setupTests.js            // 删除

以上文件删除后,页面会报错。这是因为相应的文件引用已不存在。修改下代码即可。删除后目录简化结构如下,清爽许多

|--node_modules
 |--package.json
 |--public
 |  |--favicon.ico
 |  |--index.html
 |--README.md
 |--src
 |  |--App.js
 |  |--index.js
 |  |--reportWebVitals.js

Dva搭建

React仅仅是一个视图层框架,但随着前端项目越来越复杂很多后端技术思想的也逐渐延生到前端,Dva将数据层的数据操作剥离开,在使用Dva框架前,先请确保对 React技术栈有比较全面的了解,掌握必要的React基础。Dva框架本质上是 蚂蚁金服基于 React技术栈封装的一套框架,,特点在于免去了新手手动搭建完整开发环境(Redux,React-Router等的安装)的麻烦。

Dva是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为一个轻量级的应用框架。

简单来说Dva就是把常用到的模块集成在一起,形成一定的架构规范。把React常常需要我们必须写的需要用到的引用、代码都集成在了一起,比如一些依赖、必写的一些ReactDOM.render、引入saga、redux控制台工具、provider包裹等都省去不写,大大提高我们的开发效率

项目搭建

  1. 安装dva-cli

    npm install -g dva-cli    // 全局安装 dva命令行工具
  2. 使用dva-cli创建项目

    dva new dva-web-demo   // 执行该命令将会在当前目录创建 dva-web-demo 目录,包含有初始化的项目文件
  3. 启动 dva项目

    cd dva-web-demo 
    npm start                  // 在执行 dva new 时已经自动安装好项目初始化时所需要的npm依赖包
  4. 配置 index.js

    Dva项目初始化好后,在 src 下新增或修改入口文件 index.js,Dva提供了5个可配置的API

    import dva from 'dva';
    import createHistory from 'history/createHashHistory';
    
    //1.Initialize  创建dva实例
    const app = dva({
        history: createHistory(),
    });
    
    //2.Plugins 装载插件(可选)
    app.use({});
    
    //3.Model 注册 Model
    app.model(require('./models/app').default);
    
    //4.Router 配置路由
    app.router(require('./router').default);
    
    //5.Start 启动应用
    app.start('#root');

项目初始化好后,目录结构大致如下

├── /dist/                                         // 打包目标目录
├── /src/                                          // 项目源码目录
│ ├── /components/                                 // 通用组件目录
│ ├── /models/                                     // 数据模型 
│                 └── example.js                     // model example, dva的模型是一个集合了redux中 reducer 和 store,异步action等的抽象概念。
│ ├── /services/                                   // 存放 服务相关组件或函数
│ ├── /mock/                                       // 模拟数据mock
│ ├── /routes/                                     // 与路由对应的页面
│                 └── page.js                        // 与路由规则匹配的页面组件
│ ├── index.css                                    // 项目入口css
│ ├── index.js                                     // 项目入口,手动配置开发时候开发的模块
│ └── router.js                                    // 项目路由 (默认使用React-Router中的HashRouter,所以你会看到URL最后有一个#号,可以通过使用dva-no-router禁用react-router)
├── package.json                                   // 项目依赖信息
├── .eslintrc                                      //  Eslint配置
├── .gitignore                                     //  git 忽略文件以及目录
└── .webpackrc                                     //  roadhog配置
└── README.md                                      //  开发文档

关于配置

1,app = dva(Opts):创建应用,返回 dva 实例。(注:dva 支持多实例)

opts可以配置所有的hooks

const app = dva({
     history,
     initialState,
     onError,
     onAction,
     onStateChange,
     onReducer,
     onEffect,
     onHmr,
     extraReducers,
     extraEnhancers,
});

这里比较常用的是,history的配置,一般默认的是hashHistory,如果要配置 history 为 browserHistory,可以这样:

import createHistory from 'history/createBrowserHistory';
const app = dva({
  history: createHistory(),
});

2,app.use(Hooks):配置 hooks 或者注册插件。

这里最常见的就是dva-loading插件的配置,

import createLoading from 'dva-loading';
...
app.use(createLoading(opts));

但是一般对于全局的loading我们会根据业务的不同来显示相应不同的loading图标,我们可以根据自己的需要来选择注册相应的插件。

3,app.model(ModelObject):这个是你数据逻辑处理,数据流动的地方。

export default {

  namespace: 'example',   //表示对于整个应用不同的命名空间,以便通过this.props.example访问,和当前model文件名相同就好之前的reducer名字相同,是全局state的属性,只能为字符串,不支持.的方式建立多重

  state: {initText:"hello"},     //表示当前的example中的state状态,这里可以给初始值

  subscriptions: {
    setup({ dispatch, history }) {  // 订阅,可以监听服务器连接,键盘输入,路由,状态等的变化
    },
  },

  effects: {
    *fetch({ payload }, { call, put }) { 
     //payload是从组件router传递过来的参数,
     //这里的call方法可以使用payload参数传递给后台程序进行处理这里可以调用service层的方法进行调用后端程序,
     //这里的put表示存储在当前命名空间example中,通过save方法存在当前state中
      yield put({ type: 'save' });
    },
  },

  //用来保存更新state值 上面的put方法调用这里的方法
  reducers: {
    save(state, action) {
      return { ...state, ...action.payload };
    },
  },

};

modaldva里面与我们真正进行项目开发,逻辑处理,数据流动的地方。这里面涉及到的namespaceModaleffectsreducer等概念都很重要

4,app.router(Function):注册路由表,我们做路由跳转的地方。

app.router(require('./router').default);

然后在同级目录下添加路由文件 router.js

import React from 'react';
import { Router, Route, Switch } from 'dva/router';

import App from './containers/App';
import{ Account, Articles, Channels, Editor } from './containers';
const { ArticleList } = Articles;

const RouterConfig = (({ history }) => (
    <Routerhistory={history}>
        <Switch>
            <Route path='/' component={App}>
                <IndexRoute component={Account} />
                <Route path='account' component={Account} exact />
                <Route path='articles' component={ArticleList
 exact />
                <Route path='channels' component={Channels} exact />
                <Route path='editor' component={Editor} exact />
            </Route>
        </Switch>
    </Router>
));

export default RouterConfig;

一般都是这么写的,但是如果你的项目特别的庞大,我们就要考虑到相应的性能的问题,但是入门可以先看一下这个。对于如何做到按需加载


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
TCP/IP协议 TCP/IP协议
对于开发者来说TCP/IP协议并不陌生,很多时候我们只是基于这个协议来传输数据,开发业务功能,对它的工作原理却不甚了解。对站在应用层的开发者而言,似乎也不需要去知道它的工作原理,使用它就可以了,就像开汽车的司机不需要知道发动机的工作原理也能
2020-12-27
Next 
Go语言项目笔记 Go语言项目笔记
Go语言是一门较新生的语言,对于项目管理并没有像Java那样有 maven ,gradle,ant之类的工具,早期的Go语言通过 GoPath 来管理项目的代码,不过gopath的方式管理代码带来许多不便。在Go1.11版本以后GoModu
2020-11-22
  TOC