最近接盘了一个react项目,对于没有接触过react项目的我,慌的不行。花费了一天的时间来看了react.js的文档后,开始了写react项目。在项目的过程中,传递数据真的太痛苦了,特别对于深层次组件,例如我写的一个酷我播放器页面,简直惨不忍睹,一个组件几十个数据,方法的传入,显得项目不可直视,为了赶进度也没有管,现在告一段落后,来学习了一下redux状态管理!分享写经验!

git地址:https://gitee.com/xieyong1234/redux-study.git

对于官网的描述,我就不再复述,直接先上代码结构,我对redux的结构进行的拆分。

redux-LMLPHP

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={{width:'300px',marginRight:'10px'}}/> <Button type="primary" onClick={this.addTodoItem}>submit</Button> <List style={{width:'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',width:'20px',heigth:'20px',border:'1px solid #ccc',borderRadius:'50%',textAlign:'center',lineHeight:'20px'}}>X</div></List.Item>)} /> <div style={{width:'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-LMLPHP

  redux和react并没有直接的关联,他也可以用在jq,js, ang中。现在初步的了解了redux后,可能你也发现他用起来不怎么好用,需要手动更新视图等,现在提供了一个react-redux来配合redux完成一个完整的状态管理机制。且结构更加清晰,组件化更极致。react被区分为视图ui组件和容器组件,ui展示组件只负责静态的视图层面,所有的数据,方法操作全部都在容器组件中完成,通过react-redux提供的几个方法,完成更好的实现方式!我将在下一次更新除react-redux的用法,同一个例子,到时候可以自行看到区别和用法!只要静下心,其实也都很容易理解,虽然感觉react非常复杂,难用,由于jsx的应用,使得项目写起来更费时费力,但他的结构,组件化更清晰!期待下次的更新

05-09 04:36