用React+Redux+ES6写一个最傻瓜的Hello World
最近Redux+React似乎在前端圈子里越来越火了,然而即使是官方的文档也只给出了一个TodoMVC的范例,里面上百行的代码以及过多的新概念,对于很多初学者(包括我)来说依然很复杂。 google百度搜了搜,也一直没有找到简单傻瓜如同Hello World的快速入门,所以今天花了一点时间写了个最最简单的DEMO(真的是最最简单了/w): 点这里看DEMO Github:https://github.com/starkwang/react-redux-es6-quickstart 一、开发环境搭建 1、webpack 首先我们需要webpack这个打包工具(如果你已经有了就无视吧): sudo npm install -g webpack 2、依赖包 创建一个文件夹,随便叫什么名字,比如 mkdir redux-test && cd redux-test 然后用npm安装以下依赖包:
3、Webpack的配置文件 这个项目中需要把ES6、JSX转换为浏览器可运行的ES5语法,所以我们需要使用webpack及其babel-loader来进行转换、打包。这里我们默认 //webpack.config.js module.exports = { entry: 'index.jsx',output: { filename: 'bundle.js' },module: { loaders: [{ test: /.jsx?$/,exclude: /(node_modules|bower_components)/,loader: 'babel',// 'babel-loader' is also a legal name to reference query: { presets: ['es2015','react'] } }] } }; 把这个 4、HTML 首先的首先,我们需要一张HTML页面,这个页面里有一个id为 <!DOCTYPE html> <html> <head> <title>React-Redux Hello World</title> </head> <body> <div></div> </body> <script type="text/javascript" src="bundle.js"></script> </html> 二、开始写代码吧 网上React的入门教学实在太多,不再赘述。 关于Redux,请务必读完中文文档的入门部分。 我们现在主要是要实现DEMO中的效果: 以下代码都是在同一个文件index.jsx中! 0、引入依赖包
我们需要react的本体、react-dom的 import React from 'react'; import { render } from 'react-dom'; import { createStore,bindActionCreators } from 'redux'; import { Provider,connect } from 'react-redux'; 1、Action 显然我们要定义两种事件:“文字来回切换”、“按钮点击”。 //action //我们这里并没有使用const来声明常量,实际生产中不推荐像下面这样做 function changeText(){ return { type:'CHANGE_TEXT' } } function buttonClick(){ return { type:'BUTTON_CLICK' } } 2、Reducer 对于不同的action,对应的状态转换也不一样: //reducer //最初的状态是"Hello" const initialState = { text: 'Hello' } function myApp(state = initialState,action) { switch (action.type) { case 'CHANGE_TEXT': return { text:state.text=='Hello'?'Stark':'Hello' } case 'BUTTON_CLICK': return { text: 'You just click button' } default: return { text:'Hello' } } } 3、Store Store是由Redux直接生成的: let store = createStore(myApp); 4、组件 这里一共有三个组件:文字组件 //Hello class Hello extends React.Component{ constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick(){ this.props.actions.changeText(); } render() { return ( <h1 {this.props.text} </h1> ); } } //Change class Change extends React.Component{ constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick(){ this.props.actions.buttonClick(); } render() { return ( <button >change</button> ); } } //App class App extends React.Component{ constructor(props) { super(props); } render() { //actions和text这两个props在第5步中会解释 const { actions,text} = this.props; return ( <div> <Hello acti text={text}/> <Change acti/> </div> ); } } 5、连接React组件和Redux //mapStateToProps的作用是声明,当state树变化的时候,哪些属性是我们关心的? //由于我们这个应用太小,只有一个属性,所以只有text这个字段。 function mapStateToProps(state) { return { text: state.text } } //mapDispatchToProps的作用是把store中的dispatch方法注入给组件 function mapDispatchToProps(dispatch){ return{ actions : bindActionCreators({changeText:changeText,buttonClick:buttonClick},dispatch) } } //这里实际上给了App两个props:text和actions,即第4步中的那段注释 App = connect(mapStateToProps,mapDispatchToProps)(App) 6、渲染我们的App //Provider是react-redux直接提供的 //store是我们在第3步中生成的 render( <Provider store={store}> <App /> </Provider>,document.getElementById('root') ) 7、编译、打包 还记得安装的webpack和写好的配置文件吗? 直接在项目目录下执行: webpack 然后就可以把 三、index.jsx源代码 下面是index.jsx的完整源码,可以直接复制 import React from 'react'; import {render} from 'react-dom'; import { createStore,connect} from 'react-redux'; //action function changeText(){ return { type:'CHANGE_TEXT' } } function buttonClick(){ return { type:'BUTTON_CLICK' } } //reducer const initialState = { text: 'Hello' } function myApp(state = initialState,action) { switch (action.type) { case 'CHANGE_TEXT': return { text:state.text=='Hello'?'Stark':'Hello' } case 'BUTTON_CLICK': return { text: 'You just click button' } default: return { text:'Hello' }; } } //store let store = createStore(myApp); class Hello extends React.Component{ constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick(){ this.props.actions.changeText(); } render() { return ( <h1 {this.props.text} </h1> ); } } class Change extends React.Component{ constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick(){ this.props.actions.buttonClick(); } render() { return ( <button >change</button> ); } } class App extends React.Component{ constructor(props) { super(props); } render() { const { actions,text} = this.props; return ( <div> <Hello acti text={text}/> <Change acti/> </div> ); } } function mapStateToProps(state) { return { text: state.text } } function mapDispatchToProps(dispatch){ return{ actions : bindActionCreators({changeText:changeText,dispatch) } } App = connect(mapStateToProps,mapDispatchToProps)(App) render( <Provider store={store}> <App /> </Provider>,宋体"> 四、总结 |