最近接盘了一个react项目,对于没有接触过react项目的我,慌的不行。花费了一天的时间来看了react.js的文档后,开始了写react项目。在项目的过程中,传递数据真的太痛苦了,特别对于深层次组件,例如我写的一个酷我播放器页面,简直惨不忍睹,一个组件几十个数据,方法的传入,显得项目不可直视,为了赶进度也没有管,现在告一段落后,来学习了一下redux状态管理!分享写经验!
git地址:https://gitee.com/xieyong1234/redux-study.git
对于官网的描述,我就不再复述,直接先上代码结构,我对redux的结构进行的拆分。
redux的结构无外乎就是store,state,action, reducer来组成整个数据的修改与传递。简单的来描述redux的执行过程:
1:组件出发action来告知store你所要做的事情,
2:store通过reducer来处理对应的事件,reducer返回新的完整的state对象;
3:store接受reducer返回的对象更新state;
4:store将新的值传递给组件完成视图的更新
先来说下redux的执行细节及对应的api:
1.组件通过store的dispatch方法来传递action,store.dispatch(action);
2.reducer根据action来判断执行操作,返回完整的新对象,
3.store通过subscribe方法来监听state的变化,通知页面更新。store.subscribe(function(){});
4.更新函数通过setState()来出发视图刷新,页面的数据通过store.getState()来获取整个state
现在来贴上每个对应文件的代码,便于理解
入口文件:
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; ReactDOM.render( <App />, document.getElementById('root') ); serviceWorker.unregister();
组件文件:
import React,{ Component } from 'react'; import "antd/dist/antd.css";//antd的ui import { Input, Button, List, Checkbox } from 'antd';
//引入自己定义好的action创建函数(为了拆分,便于维护) import { changeInput, add_todo_item, delete_todo_item, check_box_handler, census_check_num, delete_completed } from './store/actionCreators'; import store from './store/'; //引入store class App extends Component { constructor(props){ super(props); this.state = store.getState();//将store的state this.handleInputChange = this.handleInputChange.bind(this); this.updateState = this.updateState.bind(this); this.addTodoItem = this.addTodoItem.bind(this); this.deleteChecked = this.deleteChecked.bind(this); store.subscribe(this.updateState)//监听store里state的更新 } updateState(){ this.setState(store.getState());//出发视图更新 } handleInputChange(e){ //input输入框的数据变化 store.dispatch(changeInput(e.target.value));//调用dispatch方法,传入对应的action来改变state } addTodoItem(){ //添加 store.dispatch(add_todo_item()); } deleteTodoItem(index){ //删除一项todo store.dispatch(delete_todo_item(index)); this.censucNum() } checkboxHandler(index){ //选中checkbox store.dispatch(check_box_handler(index)); this.censucNum(); } censucNum(){ //统计选中数量 store.dispatch(census_check_num()); } deleteChecked(){ //删除所有选中 store.dispatch(delete_completed()); this.censucNum(); } render() { const { value, list, activeNum } = this.state; return <div style={{maringTop:'10px',marginLeft:'10px'}}> <Input value={value} onChange={this.handleInputChange} placeholder="todo info" style={{'300px',marginRight:'10px'}}/> <Button type="primary" onClick={this.addTodoItem}>submit</Button> <List style={{'300px',marginTop:'10px'}} bordered dataSource={list} renderItem={(item,index) => (<List.Item style={{position:'relative'}}><Checkbox checked={item.isCompleted} onChange={this.checkboxHandler.bind(this,index)} style={{marginRight:'10px'}}></Checkbox><div style={item.isCompleted ? {textDecoration:'line-through',color:'#ccc'} : {}}>{item.name}</div><div onClick={this.deleteTodoItem.bind(this,index)} style={{position:'absolute',right:'10px',top:'50%',transform:'translateY(-50%)',cursor:'pointer','20px',heigth:'20px',border:'1px solid #ccc',borderRadius:'50%',textAlign:'center',lineHeight:'20px'}}>X</div></List.Item>)} /> <div style={{'300px',height:'50px',display:'flex',justifyContent:'space-around',alignItems:'center',border:'1px solid #ccc',marginTop:'10px',borderRadius:'3px'}}> <span>{activeNum}item</span> <span onClick={this.deleteChecked} style={{cursor:'pointer'}}>delete completed</span> </div> </div> } } export default App;
store文件:index.js
import { createStore } from 'redux'; //引入redux的函数,创建store import reducer from './reducers'; //引入写好的reducer,注入store const store = createStore( reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()//应用于谷歌的redux'插件 ); export default store;
action的type类型:actionTypes.js
export const CAHNGE_INPUT_VALUE = 'change_input_value'; export const ADD_TODO_ITEM = 'add_todo_item'; export const DELETE_TODO_ITEM = 'delete_todo_item'; export const CHECK_BOX_HANDLER = 'check_box_helder'; export const CENSUS_CHECK_NUM = 'census_check_num'; export const DELETE_COMPLETED = 'delete_completed';
action的创建函数:cactionCreators.js
import { CAHNGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM, CHECK_BOX_HANDLER, CENSUS_CHECK_NUM, DELETE_COMPLETED } from './actionTypes'; export const changeInput = (value) => { //input框的创建函数,传入输入值,返回对应的action return { type: CAHNGE_INPUT_VALUE, value } } export const add_todo_item = () => { return { type:ADD_TODO_ITEM } } export const delete_todo_item = (index) => { return { type:DELETE_TODO_ITEM, index } } export const check_box_handler = (index) => { return { type:CHECK_BOX_HANDLER, index } } export const census_check_num = () => { return { type:CENSUS_CHECK_NUM } } export const delete_completed = () => { return { type:DELETE_COMPLETED } }
reducer文件:reducers.js
import { CAHNGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM, CHECK_BOX_HANDLER, CENSUS_CHECK_NUM, DELETE_COMPLETED } from './actionTypes'; const initState = { //state的默认值 value:'', list:[ { name:'1', isCompleted:false } ], activeNum:0 } export default (state=initState,action) => { //切记,reducer是一个纯函数,即输入条件相同,则输入一定相同,且不能有负面的影响;reducer中不能改变state let newState; switch(action.type){ case CAHNGE_INPUT_VALUE: return Object.assign({},state,{value:action.value}); case ADD_TODO_ITEM: newState = JSON.parse(JSON.stringify(state)); if(newState.value.trim() === '') return newState; newState.list.push({name:newState.value,isCompleted:false}); newState.value = ''; return newState; case DELETE_TODO_ITEM: newState = JSON.parse(JSON.stringify(state)); newState.list.splice(action.index,1); return newState; case CHECK_BOX_HANDLER: newState = JSON.parse(JSON.stringify(state)); newState.list[action.index].isCompleted = !newState.list[action.index].isCompleted; return newState; case CENSUS_CHECK_NUM: newState = JSON.parse(JSON.stringify(state)); let num=0; newState.list.forEach(element => { if(element.isCompleted) num++ }); return Object.assign({},state,{activeNum:num}); case DELETE_COMPLETED: newState = JSON.parse(JSON.stringify(state)); for(var i = newState.list.length-1;i>=0;i-- ){ var item = newState.list[i] if(item.isCompleted){ newState.list.splice(i,1) } } return newState; default: return state } }
至此,一个简单的redux项目就已经完成,效果如图:
redux和react并没有直接的关联,他也可以用在jq,js, ang中。现在初步的了解了redux后,可能你也发现他用起来不怎么好用,需要手动更新视图等,现在提供了一个react-redux来配合redux完成一个完整的状态管理机制。且结构更加清晰,组件化更极致。react被区分为视图ui组件和容器组件,ui展示组件只负责静态的视图层面,所有的数据,方法操作全部都在容器组件中完成,通过react-redux提供的几个方法,完成更好的实现方式!我将在下一次更新除react-redux的用法,同一个例子,到时候可以自行看到区别和用法!只要静下心,其实也都很容易理解,虽然感觉react非常复杂,难用,由于jsx的应用,使得项目写起来更费时费力,但他的结构,组件化更清晰!期待下次的更新