玩物圈前端技术栈总结(React+Redux)
本文代码模版:react-redux-webpack-boilerplate 好记性不如烂笔头,之前陆续写过几篇关于玩物圈前端所用到技术栈的总结,现在在 玩物圈PC版 上线之前,将玩物圈前端用到技术栈整体简单总结梳理下。 前端基本框架图
1、webpackwebpack是一款模块加载器兼打包工具,具体使用参考官方文档,很详细。 项目中的主要作用:
生产配置 var webpack = require('webpack'); var path = require('path'); var entry = require('./entry.js'); var templateConfig = require('./html.template.config.js').pro; var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('vendor','static/js/vendor.[hash:8].js'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require('extract-text-webpack-plugin'); var config = { entry: entry,output: { path: __dirname + '/product',publicPath: 'http://cdn.xx.com/',filename: 'static/js/[name].[chunkhash:8].js' },resolve: { extensions: ['','.js','.jsx'],// 配置可以不书写的后缀名 root: path.join(__dirname,'public/') //配置绝对路径,alias、entry中会使用 },module: { loaders: [ { test: /.js[x]?$/,include: path.resolve(__dirname,'public'),exclude: /node_modules/,loader: 'babel-loader' },{ test: /.(jpg|png|gif)$/,loader: 'url?limit=1024&name=static/images/[hash].[ext]'//小于1kb的图片转化为base64,css中其他的图片地址会被体会为打包的地址,此处用到了publicPath },{test: /.css$/,loader: ExtractTextPlugin.extract('style-loader','css-loader?sourceMap')} ] },plugins: [ commonsPlugin,new ExtractTextPlugin('static/css/[name].[chunkhash:8].css'),new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }),commonsPlugin ] }; for (var i = 0; i < templateConfig.length; i++) { config.plugins.push(new HtmlWebpackPlugin(templateConfig[i])); } module.exports = config; 参考文档:
2、BabelBabel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,JSX语法代码转为ES5代码。 3、ReactReact提供应用的 View 层,表现为组件,具体参考官方文档 主要知识点:
参考:
4、Redux(单向数据流)Redux 是 JavaScript 状态容器,提供可预测化的状态管理。本身跟react没有任何关系。 Redux 除了和 React 一起用外,还支持其它界面库。 4.1 基本思想可以参考Redux:一种更优雅的 Flux 实现
4.2 中间件Middleware类似 Express 或 Koa 框架中的中间件。它提供的是位于 action 被发起之后,到达 reducer 之前的扩展。
参考:
5、react-reduxreact-redux的作用是连接(connect)store和容器组件的。store是redux提供的,容器组件是react提供的。 5.1 组织应用的组件
容器组件:位于应用最顶层的组件,用来与redux连接的。从redux中获取数据作为props。 5.2 连接Store与组件react-redux仅仅提供两个关键模块:Provider和connect。 源码: import Provider from './components/Provider' import connect from './components/connect' export { Provider,connect }
例子: ReactDOM.render( <Provider store={store}> {/* note "routerState" here: important to pass it down */} <Handler routerState={routerState} /> </Provider>,document.getElementById('root') );
例子: import * as actionCreators from './actionCreators' function mapStateToProps(state) { return { todos: state.todos } } export default connect(mapStateToProps,actionCreators)(MyRootComponent) 参考:
6、ES6目前主流的框架(Angular2,React,Koa,Redux)全面转向ES6。项目中使用了部分ES6的明星特性。一开始我是拒绝的,不习惯,现在的感觉是:非常方便,非常爽。 6.1 Class和Module模块化:组件按模块编写以及使用、Action和Reducer按模块拆分合并、使用第三方模块,这些在项目中都是使用的是ES6的Module特性,其中编写React组件使用了ES6的Class特性。 例子: import {Types} from '../constants/base/order'; export * from './base/user'; export {fetchCart} from './base/shopCart'; export {fetchOrder} from './base/order'; export function fetchPayResult(id) { return { url: '/mall/order/payResult/' + id,method: 'GET',types: ['REQUEST',Types.FETCH_PAY_RESULT,'FAILURE'] }; } export function changePayType(payType) { return { type: Types.SELECT_PAY_TYPE,payType }; } export class Counter extends React.Component { constructor(props) { super(props); this.state = {count: props.initialCount}; } tick() { this.setState({count: this.state.count + 1}); } render() { return ( <div onClick={this.tick.bind(this)}> Clicks: {this.state.count} </div> ); } } Counter.propTypes = { initialCount: React.PropTypes.number }; Counter.defaultProps = { initialCount: 0 }; 6.2 变量结构赋值var { types,url = '',mockUrl = '',method = 'GET',dataType = 'json',data = {} } = action; 6.3 函数的扩展:箭头函数、函数参数的默认值
const noop = ()=> false; let createItem = (item,index) =><Order order={item} key={index}/>; const Coupon = (props) => ( <li> <div className="coupon-tit">抵用券</div> <div className="coupon-price"><span>¥</span><strong>{props.coupon.price}</strong></div> <div className="coupon-info"> <p>{props.coupon.code}</p> <p className="time">{props.coupon.endTime}前可用</p> </div> </li> );
export function address(state = {},action) { switch (action.type) { case Types.SELECT_ADDRESS: return objectAssign({},action.payload); ... 6.4 字符串扩展:模板字符串href={`/pc/mall/order/confirm.html?${param}`} return { mockUrl: '/static/mock/user.address.save.json',url: `/user/address/${id}`,method: 'PUT',data: {id,isDefault},Types.SET_DEFAULT_ADDRESS,'FAILURE'] }; 6.5 对象的扩展:属性的简洁表示法export const setVisibilityFilter = (filter) => { return { type: 'SET_VISIBILITY_FILTER',filter } } return { mockUrl: '/static/mock/user.address.save.json','FAILURE'] }; App.defaultProps = { user: {},tips: {visible: false},carts: [],visibleDropCart: false,visibleLoginDialog: false,switchLoginDialog() { },switchTips() { },switchDropCart() { } }; 6.6 let和constconst noop = ()=> false; let createItem = (item,index) =><Order order={item} key={index}/>; 参考:
7、GulpGulp与Grunt一样,也是一个自动任务运行器。它充分借鉴了Unix操作系统的管道(pipe)思想,很多人认为,在操作上,它要比Grunt简单。 项目中主要用到的功能:结合webpack使用、压缩js、ESLint代码检查、压缩css。 var gulp = require("gulp"); var gutil = require("gulp-util"); var minifyCss = require('gulp-minify-css'); var uglify = require('gulp-uglify'); var eslint = require('gulp-eslint'); var reporter = require('eslint-html-reporter'); var fs = require('fs'); var path = require('path'); var webpack = require("webpack"); var webpackConfigProduct = require("./webpack.production.config.js"); var webpackConfigDevelop = require("./webpack.development.config.js"); gulp.task("webpack",function(callback) { webpack(webpackConfigProduct,function(err,stats) { if (err) throw new gutil.PluginError("webpack",err); callback(); }); }); gulp.task("webpackDevelop",function(callback) { webpack(webpackConfigDevelop,err); callback(); }); }); var srcJsDir = './public/static/js/'; gulp.task('lint',function() { return gulp.src([srcJsDir + '**/*.js']) .pipe(eslint()) .pipe(eslint.format(reporter,function(results) { fs.writeFileSync(path.join(__dirname,'lint-report.html'),results); }) ); }); gulp.task("minifyJs",['webpack'],function() { return gulp.src("./product/**/*.js") .pipe(uglify({ output: { max_line_len: 100 } })) .pipe(gulp.dest("./product")); }); gulp.task("minifycssPro",function() { return gulp.src("./product/**/*.css") .pipe(minifyCss()) .pipe(gulp.dest("./product")); }); gulp.task("minifycssDev",['webpackDevelop'],function() { return gulp.src("./development/**/*.css") .pipe(minifyCss()) .pipe(gulp.dest("./development")); }); gulp.task('copyJson',function() { return gulp.src('./public/static/mock/**/*.json') .pipe(gulp.dest('./development/static/mock/')); }); gulp.task('product',['minifycssPro','minifyJs']); gulp.task('default',['minifycssDev','copyJson']); 参考:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |