一.框架基本描述
二.建立项目
- 根据上一节2、3点所说方试建立
npm init
- 到此基本开发所需的lib已安装完成
三.建立项目所需的基本资料夹和档案
- 主要所需的档案和目录如下所示
- src 【源码目录】
-
- App【存放容器组件】
-
- components 【jsx控件存放目录】
-
- reducers 【存放reducer的配置档】
-
-
- index.js
-
-
- styles 【css存放目录】
-
- store 【存放Redux的store配置档】
-
-
- configureStore.js
-
-
- templates 【index.html模板目录】
-
-
- index.html 【html模板页面,用于生成进入的页面】
-
-
- util 【存放JS工具库】
-
- entry.js 【主应用程式】
- build 【打包后的源码目录】
- resources 【存放一些外部用资源档,如支持 IE8 的js库】
- test 【存放一些测试用的程式】
- env.js【使用变量统一配置开发环境】
- webpack-config.js 【webpack项目管理配置档】
- package.json 【npm init 自动产生的包管理配置档案】
四.修改package.json配置档,使用不同的环境变数进行打包设定
- 主要增加 BUILD_LOCAL、BUILD_DEV、BUILD_UAT、BUILD_PDT四个变量进行不同环境编译的控制,其中 local和_local的配置不同是在区分 linux的系统和windows系统变量配置的方式的不同,在windows的环境中,需要使用 set去配置变量。
- 主要将scripts的区块更改为如下的设定:
"scripts": { "local": "BUILD_LOCAL=1 webpack-dev-server --devtool eval --progress --colors --hot --content-base build", "local_build": "BUILD_LOCAL=1 webpack -p", "dev": "BUILD_DEV=1 webpack-dev-server --devtool eval --progress --colors --hot --content-base build", "dev_build": "BUILD_DEV=1 webpack -p", "uat": "BUILD_UAT=1 webpack-dev-server --devtool eval --progress --colors --hot --content-base build", "uat_build": "BUILD_UAT=1 webpack -p", "pdt": "BUILD_PDT=1 webpack-dev-server --devtool eval --progress --colors --hot --content-base build", "pdt_build": "BUILD_PDT=1 webpack -p", "_local": "set BUILD_LOCAL=1&&webpack-dev-server --devtool eval --progress --colors --hot --content-base build", "_local_build": "set BUILD_LOCAL=1&&webpack -p", "_dev": "set BUILD_DEV=1&&webpack-dev-server --devtool eval --progress --colors --hot --content-base build", "_dev_build": "set BUILD_DEV=1&&webpack -p", "_uat": "set BUILD_UAT=1&&webpack-dev-server --devtool eval --progress --colors --hot --content-base build", "_uat_build": "set BUILD_UAT=1&&webpack -p", "_pdt": "set BUILD_PDT=1&&webpack-dev-server --devtool eval --progress --colors --hot --content-base build", "_pdt_build": "set BUILD_PDT=1&&webpack -p", "test": "echo \"Error: no test specified\" && exit 1" },
五.修改webpack.config.js和env.js的配置
- webpack.config.js配置档案主要增加 definePlugin 的配置,范例如下
/**
* 载入webpack需要的js模组
**/
var path = require('path');
var webpack = require('webpack');
//设定项目的根目录
var ROOT_PATH = path.resolve(__dirname);
//设定 source path
var SRC_PATH = path.resolve(__dirname, './src');
//设定应用程式进入JS档案
var APP_PATH = path.resolve(__dirname, './src/entry.js');
//设定打包结果目录
var BUILD_PATH = path.resolve(__dirname, './build');
//使用 extract-text-webpack-plugin 可以把 css 从 js 中独立抽离出来
var ExtractTextPlugin=require("extract-text-webpack-plugin");
//使用 CommonsChunkPlugin 抽取公共代码
var CommonsChunkPlugin=require("webpack/lib/optimize/CommonsChunkPlugin");
//使用 HtmlWebpackPlugin 可以帮助生成HTML文件,在body元素中,使用 script 来包含所有你的 webpack bundles
var HtmlWebpackPlugin = require('html-webpack-plugin'); //依模板生成html
// 使用 CleanPlugin 删除你以前build过的文件
var CleanPlugin = require('clean-webpack-plugin');
// 使用 CopyWebpackPlugin 拷贝资源文件到 BUILD_PATH中
var CopyWebpackPlugin = require("copy-webpack-plugin");
var definePlugin = new webpack.DefinePlugin({
__LOCAL__: JSON.stringify(JSON.parse(process.env.BUILD_LOCAL || 'false')),
__DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'false')),
__UAT__: JSON.stringify(JSON.parse(process.env.BUILD_UAT || 'false')),
__PDT__: JSON.stringify(JSON.parse(process.env.BUILD_PDT || 'false')),
__PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'true'))
});
module.exports = {
/* 提供source-map方便Debug用,若要部署至正式机,请关闭此选项 */
devtool: 'eval-source-map',
/* 配置应用程式进入js档案 */
entry: {
main:[APP_PATH],
vendor: ['jquery']
},
/* 配置输出预设的路径,和依需载入打包【将每个组件打包成自己的js,在使用时才进行载入】 */
output: {
path:BUILD_PATH,
filename:'[name].js',
chunkFilename:'components/[name].[chunkhash:5].min.js'
},
/* 表示这个依赖项是外部lib,遇到require 或 import它不需要编译,且在浏览器端对应window.React*/
externals: [{
'antd': 'window.antd',
'react': 'window.React',
'react-dom': 'window.ReactDOM',
'jquery': 'window.jQuery',
}],
/* 设定打包时查找的类型,增加查询打包速度 */
resolve:{
root:['js','jsx','css','scss','less']
},
/* 配置开启 Debug 模式,暂不知到如何使用 */
debug: true,
/* 模组Loader配置 */
module: {
loaders: [
/* 档案匹配 .js 进行 babel es6转换 */
{ test: /\.js$/,
loader: "babel", include: /src/,exclude: /node_modules/
},
/* 档案匹配 .jsx 进行 babel es6转换,然后再进行 jsx 语法转换【转换规则由右至左】*/
{ test: /\.jsx$/,
loader: "jsx!babel", include: /src/,exclude: /node_modules/
},
/* 档案匹配 .css 进行 【css样式加前缀】语法转换,【转换规则由右至左】*/
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style", "css!postcss")/*,include: /src/,exclude: /node_modules/*/
},
/* 档案匹配 .sass 进行 sass 语法转换为 css,【转换规则由右至左】*/
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css!postcss!sass'),include: /src/,exclude: /node_modules/
},
/* 档案匹配 .less 进行 less 语法转换为 css,【转换规则由右至左】*/
{
test:/\.less$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader"),include: /src/,exclude: /node_modules/
},
/* url-loader 的配置,将小于80K的静态图片转为Base64字符串,减少网路请求压力 */
{
test:/\.(png|jpg)$/,
loader:'url?limit=8192&name=images/[hash:8].[name].[ext]',include: /src//*,exclude: /node_modules/*/
}],
/* 项目兼容IE8时,需要进行 ES3的语法转换
postLoaders: [{
test: /\.js$/,
loaders: ['es3ify-loader']
},{
test: /\.jsx$/,
loaders: ['es3ify-loader']
}]*/
},
/* presets字段设定转码规则,官方提供以下的规则集,你可以根据需要安装 【预设使用 ES2015(ES6)转码规则、ES7第0阶段的转码规则和react转码规则】*/
babel: {
presets: ['es2015', 'stage-0', 'react'],
},
/* 调用autoprefixer插件,css3自动补全 */
postcss: [
require('autoprefixer')
],
/* 配置webpack开发服务器设定的Port */
devServer:{
port:8084,
host:"0.0.0.0",
colors: true, //终端中输出结果为彩色
historyApiFallback: true, //不跳转
inline: true, //实时刷新
outputPath:BUILD_PATH,
/* 代理服务器的配置 */
proxy:{
'/api/*': {
target: 'http://192.168.4.208:8083',
pathRewrite: {'^/api' : '/'},
changeOrigin: true
},
'/api/*': {
target: 'ws://192.168.4.208:8083',
pathRewrite: {'^/api' : '/'},
ws:true,
changeOrigin: true
}
}
},
/**
* webpack 常用插件配置
**/
plugins: [
definePlugin,
//new CleanPlugin(BUILD_PATH),
new CommonsChunkPlugin({
name: 'vendor',
filename: '[name]-[hash].min.js'
}),
new ExtractTextPlugin('[name].css'),
new HtmlWebpackPlugin({ //根据模板插入css/js等生成最终HTML
filename: './index.html', //生成的html存放路径,相对于 path
template: './src/templates/index.html', //html模板路径
hash: false,
}),
new webpack.optimize.UglifyJsPlugin(),
new webpack.ProvidePlugin({
ENV: ROOT_PATH+"/env.js",
Moment: 'moment', //直接从node_modules中获取
$:"jquery",
jQuery:"jquery",
"window.jQuery":"jquery"
}),
new CopyWebpackPlugin([{
from: 'resources',
to: ROOT_PATH + '/build'
},{
from: 'node_modules/jquery/dist/jquery.min.js',
to: ROOT_PATH + '/build/js'
},{
from: 'node_modules/react/dist/react.min.js',
to: ROOT_PATH + '/build/js'
},{
from: 'node_modules/react-dom/dist/react-dom.min.js',
to: ROOT_PATH + '/build/js'
},{
from: 'node_modules/antd/dist/antd.min.css',
to: ROOT_PATH + '/build/styles'
},{
from: 'node_modules/antd/dist/antd.min.js',
to: ROOT_PATH + '/build/js'
},{
from: 'test',
to: ROOT_PATH + '/build'
}
])
]
};
- env.js是环境配置模块,其配置内容如下:
if(__LOCAL__){
module.exports = {
baseUrl: 'http://localhost:8084/api/' ,
wsUrl: 'ws://localhost:8084/api/'
};
}
if(__DEV__){
module.exports = {
baseUrl: 'http://192.168.4.109:8084/api/' ,
wsUrl: 'ws://192.168.4.109:8084/api/'
};
}
if(__UAT__){
module.exports = {
baseUrl: 'http://192.168.4.109:8080/api/' ,
wsUrl: 'ws://192.168.4.109:8080/api/'
};
}
if(__PDT__){
module.exports = {
baseUrl: 'http://192.168.4.109:8080/api/' ,
wsUrl: 'ws://192.168.4.109:8080/api/'
};
}
六.撰写项目启动的entry.js程序
- entry.js 的程序主要是引入App/index.js的容器组件,其内容如下:
require('console-polyfill');
require('es6-promise');
require('babel-polyfill');
/**
* 载入应用程式主要容器组件
**/
require('./App/index.jsx');
七.撰写App/index.jsx主要容器组件
- App/index.jsx组件会使用到Redux的store和reducer,我们也需要进行相关的配置
-
- 在src目录下建立store子目录和档案configureStore.js
-
- configureStore.js的内容配置如下:
- configureStore.js的内容配置如下:
import { createStore, applyMiddleware,compose } from 'redux'
import thunk from 'redux-thunk'
import createLogger from 'redux-logger'
import reducer from '../reducers'
const logger = createLogger();
//applyMiddleware来自redux可以包装 store 的 dispatch
//thunk作用是使action创建函数可以返回一个function代替一个action对象
const createStoreWithMiddleware = compose(
//配至Redux使用的中间件,我们在开发中用到的中间件是redux-thunk和redux-logger
applyMiddleware(
thunk,
logger
),
//可以帮助我们自动生成chrome插件redux的devtool界面,用于Redux Debug用,再开发期间可已使用,上正式部署时请记得关闭
window.devToolsExtension ? window.devToolsExtension() : f => f
)(createStore)
/**
* 配置Redux的store用于存放组件state
**/
export default function configureStore(initialState) {
const store = createStoreWithMiddleware(reducer, initialState)
//热替换选项
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('../reducers', () => {
const nextReducer = require('../reducers')
store.replaceReducer(nextReducer)
})
}
return store
}
-
- 在src目录下建立reducers子目录和档案index.js
-
- 的内容如下:
- 的内容如下:
import { combineReducers } from 'redux';
import counter from '../App/Counter/counter-action.js';
//使用redux的combineReducers方法将所有action的reducer打包起来
const rootReducer = combineReducers({
counter
});
export default rootReducer;
-
- 在src/App下建立一个index.jsx的App容器组件
-
- 其内容如下:
- 其内容如下:
const React = require('react');
const ReactDOM = require('react-dom');
import {Router, Link, browserHistory} from 'react-router';
import {createHashHistory} from 'history';
import { Provider } from 'react-redux';
import configureStore from '../store/configureStore';
// 引入Antd的导航组件
import { Menu, Icon } from 'antd';
const SubMenu = Menu.SubMenu;
require('../styles/app.scss');
//ES6 语法建立App组件
export default class App extends React.Component{
constructor(props){
super(props);
//
this.state = {
current: '',
username: '管理者'
};
}
handleClick(e) {
this.setState({
current: e.key
});
}
render(){
return (
<div>
<div id="leftMenu">
<img src='images/logo.png' width="50" id="logo"/>
<Menu theme="dark"
onClick={this.handleClick.bind(this)}
style={{ width: 200 }}
mode="inline"
>
<Menu.Item key="0"><Link to="/"><Icon type="home" />首页</Link></Menu.Item>
<SubMenu key="sub9000" title={<span><Icon type="bars" /><span>测试导航</span></span>}>
<Menu.Item key="9100"><Link to="/counter">计数器</Link></Menu.Item>
</SubMenu>
</Menu>
</div>
<div id="rightWrap">
<Menu mode="horizontal">
<SubMenu title={<span><Icon type="user"/>{this.state.username}</span>}>
<Menu.Item key="setting:1">退出</Menu.Item>
</SubMenu>
</Menu>
<div className="right-box">
{ this.props.children }
</div>
</div>
</div>
)
}
}
//路由配置
const rootRoute = {
path: '/',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./index.jsx').default)
}, 'App')
},
childRoutes: [
require('./Counter/counter-route.js'),
]
}
const store = configureStore();
const root = (
<Provider store={store} key="provider">
<Router history={browserHistory} routes={rootRoute}></Router>
</Provider>
);
ReactDOM.render((
root
),document.getElementById('app'));
八.建立Counter组件
-
组件的建立,一般我们需要建立三个档案,其中有redux使用的action档案、react-router使用的route档案和组件的JSX档案,依现在开发的范例来说,基本就需要counter-action.js、counter-route.js和counter.jsx这三个档案来组成一个元件,下面我们针对各个档案进行说明;
-
counter-action.js 此档案是用于组件行为控制,依Redux的要求,要控制组件的行为是使用action的type的宣告进行action行为的控制,由reducer针对type进行相应的state更新,范例如下:
【state的更新原则使用的是new 新的state,和action所带data进行合并】
export const INCREMENT_COUNTER = 'INCREMENT_COUNTER'
export const DECREMENT_COUNTER = 'DECREMENT_COUNTER'
// initial state 初始化Profile控件state
export const initialState = {
counter:0
};
//加一的Action
export function doIncrement() {
return {
type: INCREMENT_COUNTER
}
}
//减一的Action
export function doDecrement() {
return {
type: DECREMENT_COUNTER
}
}
//奇数加一的Action,该方法返回一个方法,包含dispatch和getState两个参数,dispatch用于执行action的方法,getState返回state
export function doIncrementIfOdd() {
return (dispatch, getState) => {
//获取state对象中的counter属性值
const { counter } = getState()
//偶数则返回
if (counter % 2 === 0) {
return
}
//没有返回就执行加一
dispatch(doIncrement())
}
}
//异步加一的Action,包含一个默认参数delay,返回一个方法,一秒后加一
export function doIncrementAsync(delay = 1000) {
return dispatch => {
setTimeout(() => {
dispatch(doIncrement())
}, delay)
}
}
//上述的这些Action,在其他文件导入时候,使用import * as actions 就可以生成一个actions对象包含所有的export
//reducer其实也是个方法而已,参数是state和action,返回值是新的state
export default function counter(state = initialState, action) {
switch (action.type) {
case INCREMENT_COUNTER:
return Object.assign({},state,{counter:state.counter+1});
case DECREMENT_COUNTER:
return Object.assign({},state,{counter:state.counter-1});
default:
return state
}
}
- 配置counter-route.js,route是配置组件绑定的URL,我们配置的方式是使用路由依需载入,其内容如下:
module.exports = {
//配置组件使用的URL
path: 'counter',
//配置组件动态载入jsx档案,主要是使用require进行动态载入
getComponent(nextState, callback) {
require.ensure([], (require) => {
callback(null, require('./counter.jsx').default)
}, 'Counter')
}
}
- 接下来是主要的组件设计档案 counter.jsx 其内容如下:
import React, { Component, PropTypes } from 'react'
class Counter extends Component {
constructor(props){
super(props);
this.props.doIncrement();
}
componentWillMount(){
}
render() {
//从组件的props属性中导入四个方法和一个变量
const { doIncrement, doIncrementIfOdd, doIncrementAsync, doDecrement, counter } = this.props;
console.log('doIncrement action:',this.props);
//渲染组件,包括一个数字,四个按钮
return (
<p>
Clicked: {counter.counter} times
{' '}
<button onClick={doIncrement}>+</button>
{' '}
<button onClick={doDecrement}>-</button>
{' '}
<button onClick={doIncrementIfOdd}>Increment if odd</button>
{' '}
<button onClick={() => doIncrementAsync()}>Increment async</button>
</p>
)
}
}
//限制组件的props安全
Counter.propTypes = {
//increment必须为fucntion,且必须存在
doIncrement: PropTypes.func.isRequired,
doIncrementIfOdd: PropTypes.func.isRequired,
doIncrementAsync: PropTypes.func.isRequired,
doDecrement: PropTypes.func.isRequired,
//counter必须为数字,且必须存在
counter: PropTypes.number.isRequired
};
/**
* React组件和Redux的绑定
*/
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as CounterActions from './counter-action';
//将state.counter绑定到props的counter
function mapStateToProps(state) {
return {
counter:state.counter
}
}
//将counter-action的所有方法绑定到props上
function mapDispatchToProps(dispatch) {
return bindActionCreators(CounterActions, dispatch)
}
//通过react-redux提供的connect方法将我们需要的state中的数据和actions中的方法绑定到props上
export default connect(mapStateToProps, mapDispatchToProps)(Counter)
到此React和Redux整合的基本范例已结束,谢谢
相关推荐
综上所述,通过React、Ant Design和Redux的结合,我们可以构建出一个功能完备、易扩展的后台管理系统,覆盖从用户登录、权限管理到业务操作的全过程。这个系统不仅能满足企业级应用的需求,还能为开发者提供高效的...
【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的...基于react+react-router+redux+AntD+Echarts+es6+webpack的共享单车后台管理系统源码+项目说明.zip
react-redux-antd-starter, 一个反应 Redux Ant 设计前端样板文件 react-redux-antd-starter一个反应 Redux ant设计前端样板文件。反作用力Redux蚂蚁设计反应路由器反应路由器 ReduxRedux操作BabelPostCSS较少CSS...
该架构已解决大部分坑,主要用于react@18.2.0PC端,在使用项目前请确保已安装node、yarn工具,node版本18+,此项目构建主要集成:axios、antd、sass、vite、sass、react V18,其中还会介绍到如何跨页面传递数据、...
【项目资源】: 包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括STM32、ESP8266、PHP、QT、Linux、iOS、C++...
React+antd后台管理系统模板是一个利用React前端框架和antd UI库构建的管理界面示例项目。这个模板主要用于开发者熟悉React和antd组件库的使用,同时也展示了如何在React应用中集成react-router进行页面路由管理。让...
react+antd搭建前端管理框架(***支持响应式***),主要模块分为:菜单、选项卡、面包屑;通过路由监听,实现三个模块之间的联动(同时监听浏览器);状态采用react-redux进行集中管理。目前只包含前端代码,未与...
基于node.js、vue、mongodb等技术构建的web系统,界面美观,功能齐全,适合用作毕业设计、课程设计作业等,项目均经过测试,可快速部署运行! 基于node.js、vue、mongodb等技术构建的web系统,界面美观,功能齐全,...
【标题】中的“antd-react-admin...总的来说,这个项目涉及到了React的全栈开发流程,包括前端UI设计、数据处理、路由控制以及测试和部署等多个环节,对于想要深入学习React和Antd的开发者来说,是一个很好的实践平台。
标题中的“react-最好用的reactreduxreactrouterantd脚手架”表明这是一个基于React、Redux、React-Router和Ant Design的开发框架或者模板项目。这个框架整合了四个关键的JavaScript库,为创建复杂的单页应用(SPA)...
在本教程中,我们将深入探讨如何利用antd来创建一个具有增、删、编辑功能的表格,并且会针对React 16.2和React 16.3这两个不同版本来展示两种实现方式。 **React 16.2 实现** 在React 16.2中,我们可以利用antd的...
【资源说明】 1、该资源内项目代码都是经过测试运行成功,功能正常的情况下才上传的,请放心下载使用。...基于react+react-router+redux+AntD+Echarts+es6+webpack的共享单车后台管理系统源码+项目说明.zip
本“基于React+antd的后台管理模板”是针对企业级后台管理系统设计的,它充分利用了React的灵活性和antd的实用性,为开发者提供了一个快速开发后台应用的基础框架。 1. **React组件化开发** React的核心思想是组件...
标题中的“react-以antd为基础组件构建的一套中后台管理系统的基本架构模板”表明这是一个基于React技术栈,并利用Ant Design(antd)库构建的用于中后台管理系统的框架模板。Ant Design是一个流行的React UI组件库...
这个"react+redux+reactRouter+webpack+antd Demo"是一个综合性的项目,它展示了如何将这些技术有效地整合在一起,创建出一个功能完备的前端应用。 **React** 是一个由Facebook开发的用于构建用户界面的JavaScript...
本工程主要基于react + redux +不可变+更少+ ES6 / 7 + webpack2.0 + fetch + react-router + antd(1.x)实现的SPA后台管理系统模板。 如果觉得不错的话,请star一下吧 :smiling_face_with_smiling_eyes: 编码时间...
通过上述步骤和关键技术点的解释,我们可以看到如何利用React、Antd和Redux来构建一个待办事项管理应用。在学习和应用这些概念时,理解各个部分是如何协同工作的对于构建高效、可维护的前端应用至关重要。
首先,让我们了解一下`react+antd拖拽生成自定义表单.rar`这个项目的核心概念。项目使用TypeScript(TS)进行编写,这是一种在JavaScript基础上添加静态类型检查的超集。TypeScript提供更好的代码工具支持,有助于...
"react-结合react全家桶antd实现的企业级网站开发模板"是一个基于React技术栈的项目,它整合了React的相关生态工具,如Redux、React Router、Webpack等,并且采用了流行的Ant Design库来提升界面的用户体验。...
功能列表 在开发版本上热重载/浏览器同步/ redux devtools 在生产版本上最小化/ chunkhash / trackJS ...git clone git@github.com:Justin-lu/react-redux-antd.git demo cd demo yarn # run dev npm run start # run