基于create-react-app官方脚手架搭建dva模式的项目(一)

思索良久,决定还是记录下心得体会:一个基于react-app" title="create-react-app">create-react-app官方脚手架,搭建起来的dva开发模式的react项目。
当然现今的前端市场如此强大,你可以在网络上找到你想要的任何脚手架,并且很多可以开箱即用,不可否认它们很优秀,开发它们的人或团队更值得我们竖起大拇指,为他们点赞!比较适合国人还是阿里系的一套react开发脚手架,dva-cli,antd,Umi等,当然gitHub上也有诸多优秀的脚手架,有兴趣的同学可以自行查阅学习。
这里,仅仅以react官方脚手架开启项目,安装采用dva方式的,构建项目,展示记录过程中遇到的各种点和Keng,若你也遇到类似问题,也许能帮上你。
1 安装create-react-app(鉴于国内网络以下使用cnpm,具体配置网上可找大量资料)
[javascript] view plain copy
- cnpm i create-react-app -g
 
2 创建项目,目录名project
[javascript] view plain copy
- create-react-app project
 
等待命令执行完成,教授叫会为你安装好基础的组件包,目录生成完毕如下:
这就是脚手架标准目录,我们再来看下package.json文件如下:
[javascript] view plain copy
- {
 - "name": "project",
 - "version": "0.1.0",
 - "private": true,
 - "dependencies": {
 - "react": "^16.4.0",
 - "react-dom": "^16.4.0",
 - "react-scripts": "1.1.4"
 - },
 - "scripts": {
 - "start": "react-scripts start",
 - "build": "react-scripts build",
 - "test": "react-scripts test --env=jsdom",
 - "eject": "react-scripts eject"
 - }
 - }
 
如上所示,很干净的目录。
此时已可运行npm start运行起来项目了,默认端口3000,效果如图:
注意scripts执行命令中有一个eject,意为弹射暴露出所有配置,其实脚手架还是为我们封装了一些东西的,这里我们就暴露出所有配置吧。
运行npm run eject,一旦选择eject,那么所封装的组件依赖和项目结构会有所变化,如图:
我们打开package.json文件如下所示,是暴露出的依赖配置项,可以看到已经为我们安装好webpack,babel,eslint等:
[javascript] view plain copy
- {
 - "name": "project",
 - "version": "0.1.0",
 - "private": true,
 - "dependencies": {
 - "autoprefixer": "7.1.6",
 - "babel-core": "6.26.0",
 - "babel-eslint": "7.2.3",
 - "babel-jest": "20.0.3",
 - "babel-loader": "7.1.2",
 - "babel-preset-react-app": "^3.1.1",
 - "babel-runtime": "6.26.0",
 - "case-sensitive-paths-webpack-plugin": "2.1.1",
 - "chalk": "1.1.3",
 - "css-loader": "0.28.7",
 - "dotenv": "4.0.0",
 - "dotenv-expand": "4.2.0",
 - "eslint": "4.10.0",
 - "eslint-config-react-app": "^2.1.0",
 - "eslint-loader": "1.9.0",
 - "eslint-plugin-flowtype": "2.39.1",
 - "eslint-plugin-import": "2.8.0",
 - "eslint-plugin-jsx-a11y": "5.1.1",
 - "eslint-plugin-react": "7.4.0",
 - "extract-text-webpack-plugin": "3.0.2",
 - "file-loader": "1.1.5",
 - "fs-extra": "3.0.1",
 - "html-webpack-plugin": "2.29.0",
 - "jest": "20.0.4",
 - "object-assign": "4.1.1",
 - "postcss-flexbugs-fixes": "3.2.0",
 - "postcss-loader": "2.0.8",
 - "promise": "8.0.1",
 - "raf": "3.4.0",
 - "react": "^16.4.0",
 - "react-dev-utils": "^5.0.1",
 - "react-dom": "^16.4.0",
 - "resolve": "1.6.0",
 - "style-loader": "0.19.0",
 - "sw-precache-webpack-plugin": "0.11.4",
 - "url-loader": "0.6.2",
 - "webpack": "3.8.1",
 - "webpack-dev-server": "2.9.4",
 - "webpack-manifest-plugin": "1.3.2",
 - "whatwg-fetch": "2.0.3"
 - },
 - "scripts": {
 - "start": "node scripts/start.js",
 - "build": "node scripts/build.js",
 - "test": "node scripts/test.js --env=jsdom"
 - },
 - "jest": {
 - "collectCoverageFrom": [
 - "src/**/*.{js,jsx,mjs}"
 - ],
 - "setupFiles": [
 - "<rootDir>/config/polyfills.js"
 - ],
 - "testMatch": [
 - "<rootDir>/src/**/__tests__/**/*.{js,jsx,mjs}",
 - "<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs}"
 - ],
 - "testEnvironment": "node",
 - "testURL": "http://localhost",
 - "transform": {
 - "^.+\\.(js|jsx|mjs)$": "<rootDir>/node_modules/babel-jest",
 - "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
 - "^(?!.*\\.(js|jsx|mjs|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
 - },
 - "transformIgnorePatterns": [
 - "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$"
 - ],
 - "moduleNameMapper": {
 - "^react-native$": "react-native-web"
 - },
 - "moduleFileExtensions": [
 - "web.js",
 - "js",
 - "json",
 - "web.jsx",
 - "jsx",
 - "node",
 - "mjs"
 - ]
 - },
 - "babel": {
 - "presets": [
 - "react-app"
 - ]
 - },
 - "eslintConfig": {
 - "extends": "react-app"
 - }
 - }
 
此处我本地更改下3000端口为9999,避免与其他本地项目冲突,安装cross-env:
[javascript] view plain copy
- cnpm i cross-env
 
修改start命令为:
[javascript] view plain copy
- - "start": "node scripts/start.js",
 - + "start": "cross-env PORT=9999 node scripts/start.js",
 
然后启动:npm start 效果如图:
3 安装dva库(dva也有自己的脚手架dva-cli,也可快速构建项目,目前已升至2.x版本,采用[email protected]路由版本)
[javascript] view plain copy
- cnpm i dva --save
 
安装history组件,等会后面会用到,主要做BrowserHistory浏览器历史功能,有兴趣的同学可网上自行学习。
4 改造项目为dva模式(不了解dva的同学可网上自行学习),在src目录下新建目录:models,services,routes,utils(utils将来存放配置文件和工具方法),如图:
5 路由设计,简单点暂设计为三个demo地址,分别如下:
(1)http://localhost:9999/aaa
(2)http://localhost:9999/aaa/bbb
(3)http://localhost:9999/ccc
6 组件设计,在routes目录下新建三个文件:AAA.js BBB.js CCC.js 如图:
代码分别为:
AAA.js
[javascript] view plain copy
- import React, { Component } from 'react';
 - class AAA extends Component {
 - render() {
 - return (
 - <div>
 - <p>
 - AAA页
 - </p>
 - </div>
 - );
 - }
 - }
 - export default AAA;
 
BBB.js
[javascript] view plain copy
- import React, { Component } from 'react';
 - class BBB extends Component {
 - render() {
 - return (
 - <div>
 - <p>
 - BBB页
 - </p>
 - </div>
 - );
 - }
 - }
 - export default BBB;
 
CCC.js
[javascript] view plain copy
- import React, { Component } from 'react';
 - class CCC extends Component {
 - render() {
 - return (
 - <div>
 - <p>
 - CCC页
 - </p>
 - </div>
 - );
 - }
 - }
 - export default CCC;
 
7 model设计,在model下新建四个文件:aaa.js bbb.js ccc.js 和app.js(app作为全局model使用,将来存放全局变量,如国际化参数,登录用户信息等)
代码分别为:
aaa.js
[javascript] view plain copy
- export default {
 - namespace: 'aaa',
 - state: {
 - name:'这是aaa的model'
 - },
 - subscriptions: {
 - },
 - effects: {
 - },
 - reducers: {
 - },
 - };
 
bbb.js
[javascript] view plain copy
- export default {
 - namespace: 'bbb',
 - state: {
 - name:'这是bbb的model'
 - },
 - subscriptions: {
 - },
 - effects: {
 - },
 - reducers: {
 - },
 - };
 
ccc.js
[javascript] view plain copy
- export default {
 - namespace: 'ccc',
 - state: {
 - name:'这是ccc的model'
 - },
 - subscriptions: {
 - },
 - effects: {
 - },
 - reducers: {
 - },
 - };
 
app.js
[javascript] view plain copy
- export default {
 - namespace: 'app',
 - state: {
 - name:'这是app的model'
 - },
 - subscriptions: {
 - },
 - effects: {
 - },
 - reducers: {
 - },
 - };
 
8 src目录下创建router.js路由控制文件,其中menuGlobal后期会提出到配置文件中,此处暂先这样放便于查看,大家发现其中也定义了id,pid,name,icon等字段,这些并不是dva路由必须字段,没错这些事自定义的字段,将来会用到,菜单关系,菜单是否显示,和icon图标等
[javascript] view plain copy
- import React from 'react';
 - import { Router, Route, Switch } from 'dva/router';
 - import dynamic from 'dva/dynamic'
 - const menuGlobal=[
 - {
 - id:'aaa',
 - pid:'0',
 - name:'aaa页',
 - icon:'user',
 - path: '/aaa',
 - models: () => [import('./models/aaa')], //models可多个
 - component: () => import('./routes/AAA'),
 - },
 - {
 - id:'bbb',
 - pid:'0',
 - name:'bbb页',
 - icon:'user',
 - path: '/aaa/bbb',
 - models: () => [import('./models/bbb')], //models可多个
 - component: () => import('./routes/BBB'),
 - },
 - {
 - id:'ccc',
 - pid:'0',
 - name:'ccc页',
 - icon:'user',
 - path: '/ccc',
 - models: () => [import('./models/ccc')], //models可多个
 - component: () => import('./routes/CCC'),
 - },
 - ];
 - function RouterConfig({ history, app }) {
 - return (
 - <Router history={history}>
 - <Switch>
 - {
 - menuGlobal.map(({path,...dynamics},index)=>(
 - <Route
 - key={index}
 - path={path}
 - exact
 - component={dynamic({
 - app,
 - ...dynamics
 - })}
 - />
 - ))
 - }
 - </Switch>
 - </Router>
 - );
 - }
 - export default RouterConfig;
 
9 修改src目录下index.js入口文件:
[javascript] view plain copy
- import dva from 'dva';
 - import './index.css';
 - import createHistory from 'history/createBrowserHistory'
 - // 1. Initialize
 - const app = dva({
 - history:createHistory()
 - });
 - // 2. Plugins
 - // app.use({});
 - // 3. Model
 - app.model(require('./models/app').default);
 - // 4. Router
 - app.router(require('./router').default);
 - // 5. Start
 - app.start('#root');
 
至此,dva的改造基本完毕,后续还有其他的细节补充,运行起来吧:npm start
效果如图:
试试看,基本的路由已经OK了,接下来,我们将进行对以上主体构造的细节坐下补充。
此处路由只是通过浏览器地址栏直接访问的形式,我们还需要增加路由跳转<Link>
(1)AAA.js中引入import { Link } from 'dva/router'; 并增加跳转链接如下:
[javascript] view plain copy
- import React, { Component } from 'react';
 - import { Link } from 'dva/router';
 - class AAA extends Component {
 - render() {
 - return (
 - <div>
 - <p>
 - AAA页
 - </p>
 - <Link to={'/aaa/bbb'}>去BBB页面</Link>
 - <br />
 - <Link to={'/ccc'}>去CCC页面</Link>
 - </div>
 - );
 - }
 - }
 - export default AAA;
 
(1)BBB.js中引入import { Link } from 'dva/router'; 并增加跳转链接如下:
[javascript] view plain copy
- import React, { Component } from 'react';
 - import { Link } from 'dva/router';
 - class BBB extends Component {
 - render() {
 - return (
 - <div>
 - <p>
 - BBB页
 - </p>
 - <Link to={'/aaa'}>去AAA页面</Link>
 - <br />
 - <Link to={'/ccc'}>去CCC页面</Link>
 - </div>
 - );
 - }
 - }
 - export default BBB;
 
(1)CCC.js中引入import { Link } from 'dva/router'; 并增加跳转链接如下:
[javascript] view plain copy
- import React, { Component } from 'react';
 - import { Link } from 'dva/router';
 - class CCC extends Component {
 - render() {
 - return (
 - <div>
 - <p>
 - CCC页
 - </p>
 - <Link to={'/aaa'}>去AAA页面</Link>
 - <br />
 - <Link to={'/aaa/bbb'}>去BBB页面</Link>
 - </div>
 - );
 - }
 - }
 - export default CCC;
 
此时页面中已有链接,三个页面可相互跳转了。
现在我们将router.js中的menuGlobal提出,放于公用文件中,首先在utils下新建文件config.js和index.js 代码分别如下:
config.js文件:
[javascript] view plain copy
- const menuGlobal=[
 - {
 - id:'aaa',
 - pid:'0',
 - name:'aaa页',
 - icon:'user',
 - path: '/aaa',
 - models: () => [import('../models/aaa')], //models可多个
 - component: () => import('../routes/AAA'),
 - },
 - {
 - id:'bbb',
 - pid:'0',
 - name:'bbb页',
 - icon:'user',
 - path: '/aaa/bbb',
 - models: () => [import('../models/bbb')], //models可多个
 - component: () => import('../routes/BBB'),
 - },
 - {
 - id:'ccc',
 - pid:'0',
 - name:'ccc页',
 - icon:'user',
 - path: '/ccc',
 - models: () => [import('../models/ccc')], //models可多个
 - component: () => import('../routes/CCC'),
 - },
 - ];
 - export default {
 - menuGlobal
 - }
 
index.js文件(之后utils中的配置文件,均可在index.js暴露出去):
[javascript] view plain copy
- import config from './config';
 - export {
 - config
 - }
 
修改src下的router.js文件,如下:
[javascript] view plain copy
- import React from 'react';
 - import { Router, Route, Switch } from 'dva/router';
 - import dynamic from 'dva/dynamic'
 - import {config} from './utils'
 - const { menuGlobal } = config
 - function RouterConfig({ history, app }) {
 - return (
 - <Router history={history}>
 - <Switch>
 - {
 - menuGlobal.map(({path,...dynamics},index)=>(
 - <Route
 - key={index}
 - path={path}
 - exact
 - component={dynamic({
 - app,
 - ...dynamics
 - })}
 - />
 - ))
 - }
 - </Switch>
 - </Router>
 - );
 - }
 - export default RouterConfig;
 
刷新页面即可,之所以把menu提出配置文件中,便于管理和后期拓展。
以上是 基于create-react-app官方脚手架搭建dva模式的项目(一) 的全部内容, 来源链接: utcz.com/z/383253.html

