本文首发在个人我的博客:http://muyunyun.cn/posts/9bfb...css
使用React技术栈搭建一个后台管理系统最初是为了上手公司的业务,后来发现这个项目还能把平时遇到的有趣的demo给整合进去。此文尝试对相关的技术栈以及如何在该项目中引人Redux进行分析。html
项目地址前端
小模块展现:node
redux在项目中的运用demo展现react
├── build.js 项目打包后的文件 ├── config webpack配置文件 │ ├──... │ ├──webpack.config.dev.js 开发环境配置 │ ├──webpack.config.prod.js 生产环境配置 ├── node_modules node模块目录 ├── public │ └──index.html ├── scripts │ ├── build.js 打包项目文件 │ ├── start.js 启动项目文件 │ └── test.js 测试项目文件 ├── src │ ├── client 汇聚(入口)目录 │ ├── common 核心目录 │ │ ├── actions redux中的action │ │ ├── components 通用功能组件 │ │ ├── container 通用样式组件 │ │ ├── images │ │ ├── pages 页面模块 │ │ ├── reducers redux中的reducer │ │ ├── utils 工具类 │ │ │ ├── config.js 通用配置 │ │ │ ├── menu.js 菜单配置 │ │ │ └── ajax.js ajax模块(往后用到) │ │ └── routes.js 前端路由 │ └── server 服务端目录(往后用到) │ └── controller ├── .gitignore ├── package.json ├── README.md └── yarn.lock
项目的初始结构和构造缘由已罗列如上,因为过些日子会引人ts,因此项目结构必然还会改动,但确定基于这基本雏形扩展的。webpack
下面对目录结构做如下说明git
项目最初始是用 create-react-app 初始化的,create-react-app 是Facebook官方提供的 React 脚手架,也是业界最优秀的 React 应用开发工具之一;github
client 做为入口目录,到时候能够把第三方中间件也放在此处;web
container 和 components 存放的都是 react 组件,区别以下表。可是我把和样式有关的组件就放在container中,把和功能有关的模块(好比本身分装的表格组件、弹出输入框组件等)就放到components中,若往后有须要,container 和 component 组件都是能够在 Redux 数据流中的。ajax
container | component | |
---|---|---|
目的 | 如何工做(数据获取,状态更新) | 如何显示(样式,布局) |
是否在 Redux 数据流中 | 是 | 否 |
读取数据 | 从 Redux 获取 state | 从 props 获取数据 |
修改数据 | 向 Redux 派发 actions | 从 props 调用回调函数 |
实现方式 | 向react-redux生成 | 手写 |
ajax 模块到时候计划用 fetch 封装一个ajax,感受使用 fetch 仍是蛮便利的。
server 层就是做为网关层,往后计划用来写 node 的。
虽然用到的技术栈众多,可是本身也谈不上熟练运用,多半是边查API边用的,因此只罗列些本身用相关的技术栈解决的点;
4月的时候 create-react-app 仍是基于 webpack(1.x) 构建的,5月27号升到了webpack(2.6),因而我也进行了 webpack 的版本升级。
babel-plugin-import 是一个用于按需加载组件代码和样式的 babel 插件,使用此插件后,在引人 antd 相应模块就能实现按需引人,在config/webpack.config.dev.js 文件中做以下修改:
{ test: /\.(js|jsx)$/, include: paths.appSrc, loader: require.resolve('babel-loader'), options: { plugins: [ "transform-decorators-legacy", // 引人 ES7 的装饰器 @ ['import', [{ libraryName: 'antd', style: true }]], ], cacheDirectory: true, }, },
首先引人 less-loader 来加载 less 样式,同时修改 config/webpack.config.dev.js 文件
test: /\.less$/, use: [ require.resolve('style-loader'), require.resolve('css-loader'), { loader: require.resolve('postcss-loader'), options: { ident: 'postcss', //https://webpack.js.org/guides/migrating/#complex-options plugins: () => [ require('postcss-flexbugs-fixes'), autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway ], flexbox: 'no-2009', }), ], }, }, { loader: require.resolve('less-loader'), options: { modifyVars: { "@primary-color": "#1DA57A" }, // 这里利用了 less-loader 的 modifyVars 来进行主题配置, 变量和其余配置方式能够参考 [配置主题](https://user-gold-cdn.xitu.io/2017/6/15/e8ba356d7b10cec196d48159e41b6e6e) 文档。 }, }, ], },
用到了 gh-pages ,使用 npm run deploy 一键发布到本身的gh-pages上,姑且把gh-pages当成生产环境吧,因此在修改config/webpack.config.dev.js 文件的同时也要对 config/webpack.config.prod.js 做出如出一辙的修改。
alias: { 'react-native': 'react-native-web', components: path.resolve(__dirname, '..') + '/src/common/components', container: path.resolve(__dirname, '..') + '/src/common/container', images: path.resolve(__dirname, '..') + '/src/common/images', pages: path.resolve(__dirname, '..') + '/src/common/pages', utils: path.resolve(__dirname, '..') + '/src/common/utils', data: path.resolve(__dirname, '..') + '/src/server/data', actions: path.resolve(__dirname, '..') + '/src/common/actions', reducers: path.resolve(__dirname, '..') + '/src/common/reducers', },
配置了引用路径的缩写后,就能够在任意地方如这样引用,好比
import Table from 'components/table'
antd是(蚂蚁金服体验技术部)通过大量的项目实践和总结,沉淀出的一个中台设计语言 Ant Design,使用者包括蚂蚁金服、阿里巴巴、口碑、美团、滴滴等一系列知名公司,并且我从他们的设计理念也学到了不少关于UI、UX的知识。
该项目采用的是antd最新的版本2.10.0,因为2.x的版本和1.x的版本仍是相差蛮大的,以前参考的项目(基于1.x)改起来太费劲,因此在组件那块就干脆本身从新封装了一遍。这部分知识点建议多看文档,官方更新仍是很是勤快的。
react-router 4.x和2.x的差别又是特别的大,召唤文档,网上基本上都仍是2.x的教程,看过文档以后,反正简而言之其就是要让使用者更容易上手。印象最深的是之前嵌套路由写法在4.x中写到同层了。以下示例他们的效果是相同的。
2.x:
<Route path="/" component={App}> <Route path="/aaaa" component={AAAA} /> <Route path="/bbbb" component={BBBB} /> </Route>
4.x:
<Route path="/" component={App} /> <Route path="/aaaa" component={AAAA} /> <Route path="/bbbb" component={BBBB} />
fetch 使用比较简单,基本的 promise 用法以下
fetch(url).then(response => response.json()) .then(data => console.log(data)) .catch(e => console.log("Oops, error", e))
此外还能这样用
try { let response = await fetch(url); let data = await response.json(); console.log(data); } catch(e) { console.log("Oops, error", e); }
可是其简洁的特色是为了让咱们能够自定义其扩展,仍是其自己就还不完善呢?我在调用 JSONP 的请求时,发现其不支持对 JSONP 的调用,所幸社区仍是很给力地找到了 fetch-jsonp 这个模块,实现了对百度音乐接口调用。fetch-jsonp使用也和 fetch 相似,代码以下
fetchJsonp(url,{method: 'GET'}) .then((res) =>res.json()) .then((data) => {})
使用了redux也已经有段时日了,我对redux的定义就是更好的管理组件的状态,一旦应用的逻辑复杂起来,各类组件状态、界面耦合起来,就容易出岔子,redux就是为了解决这个而诞生的,让咱们能够更多地关注UI层,而下降对状态的关注。
画了一幅比较简陋的图来讲明 redux 的大体流程,假设首先经过鼠标点击页面上的按钮触发了一个行为(action),这时咱们叫了一辆出租车 dispatch() 将这个 action 带到了终点站 store。这时候 store 就会经过 reducer 函数返回一个新的状态 state,从而改变 UI 显示。以前也写了篇深刻Redux架构
下面经过把 代办事项 这个demo运用到后台管理系统中来说解 Redux 在其中的运用。
首先,在入口目录建立 store
const store = createStore(rootReducer) ReactDOM.render( <Provider store={store}> { routes } </Provider>, document.getElementById('root') );
接着,我使用了 redux-actions 这个模块。使用 redux-actions 的好处是能简化大量对 action 的声明,以及能简化 reducer 的写法。
代办事项的 actions 文件片断(拿展现所有任务、已完成任务、未完成任务的 action 举例):
import { createAction } from 'redux-actions' export const setVisibility = createAction('SET_VISIBILITY')
没使用 redux-actions 时,actions 写法以下,可看出着实麻烦了很多,
export const setVisibility = (filter) => { return { type: "SET_VISIBILITY", filter } }
相应的代办事项的 reducers 文件片断:
export const setVisibility = handleActions({ 'SET_VISIBILITY'(state, action) { return { ...state, ...action.payload} } }, 'SHOW_ALL')
使用 redux-actions 后,只要进行以下调用,reducers文件里的SET_VISIBILITY
的 action 就能捕获到SHOW_ALL
这个状态。
import { setVisibility } from 'actions/todoList' @connect( (state) => ({ setVisibility: state.setVisibility, // 这个 setVisibility 是取自 reducers 的 }) ) dispatch(this.props.dispatch(setVisibility('SHOW_ALL')))
connect 来自 react-redux,这里的 @ 是 ES7里的装饰器的用法,使用它以后又能减小很多的代码量,原来还要写 mapStateToProps
、mapDispatchToProps
。
计划在该项目把平时工做、学习中遇到的react案例抽离成demo展示出来,因此之后还会多出一些模块。另外过段时间会在该项目中引人 typescript,若是还有精力的话,能够在这个项目上折腾下网关层。喜欢这个项目的话,点我 Star。