美文网首页
14.redux代码中使用19-05-15

14.redux代码中使用19-05-15

作者: 你坤儿姐 | 来源:发表于2019-05-16 12:03 被阅读0次

    安装redux devtools工具

    打开

    屏幕快照 2019-05-15 16.40.50.png
    到chrome网上应用商店,搜索 屏幕快照 2019-05-15 16.46.49.png
    点击 添加到Chrome
    屏幕快照 2019-05-15 16.49.54.png
    点击the instructions将下图代码添加到store的index.js文件
    Snip20190515_1.png
    const store = createStore(
      reducer,
       window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    );
    

    操作完成 Redux下如图:


    屏幕快照 2019-05-15 16.56.45.png

    介绍redux使用流程

    1.安装:yarn add redux
    2.在src文件夹下创建store文件夹,并在store文件夹下创建index.js文件,在store目录下再创建ruducer.js

    store文件夹中index.js

    import { createStore } from 'redux';
    import reducer from './reducer'
    
    const store = createStore(reducer);
    
    export default store;
    

    reducer.js

    const defaultState = {
      inputValue:'123',
      list: [1,2]
    }
    //state指的是整个store里的数据
    export default (state = defaultState, action) => {
        return state;
    }
    

    例1

    在input中添加onChange方法使输入框输入文字改变,实现Input框的功能

     handleInputChange(e){
          const action = {
              type: 'change_input_value',
              value: e.target.value //现在的值
          }
          store.dispatch(action); //调用store.dispatch方法将action传给store,store会自动的把之前的数据和action转发给reducer.
          console.log(e.target.value);
      }
    

    打开reducer,reducer可以接受传过来的state和action了
    state指的是store里面上一次存储的数据,action指的是用户传过来的那句话。reducer对之前的数据进行处理返回一个新的数据给store:

    //state指的是整个store里的数据
    export default (state = defaultState, action) => {
        if (action.type === 'change_input_value'){
          //reducer可以接收state但绝对不可以修改state
          //对之前的state进行深拷贝
          const newState = JSON.parse(JSON.stringify(state));
          //让newState的inputValue等于新的传过来的新的value值
          newState.inputValue = action.value;
          return newState;//return出来的数据实际上返回给了store,store用新数据替换旧数据
        }
        // console.log(state, action);
        return state;
    }
    

    reducer处理完数据并store更新完数据之后,在组件中做如下处理使组件更新:
    在组件中,例如Todolist.js组件中的constructor中添加store.subscribe();去订阅store,只要store改变store.subscribe()里的函数就会被执行。

    constructor(props) {
          super(props);
          this.state = store.getState();
          this.handleStoreChange = this.handleStoreChange.bind(this);
          store.subscribe(this.handleStoreChange);
        }
    
     handleStoreChange(){
          // console.log('store changed');
    //当我感知到store的数据发生变化的时候,就调用store.getState()方法从store里面重新取一次数据,然后调用setState替换掉当前组件里的数据。
        this.setState(store.getState());
      }
    

    例2

    做Todolist列表功能,当点击提交按钮时,把输入的数据存到
    const defaultState = { inputValue:'123', list: [1,2] }的list数组中:
    在组件中给提交按钮绑定事件:

     <Button type="primary" onClick={this.handleBtnClick}>提交</Button>
    

    1.创建action,并发给store,store将之前数据以及action转发给reducer

    handleBtnClick(){
          const action = {
            type: 'add_todo_item'
          };
          store.dispatch(action);
      }
    

    2.reducer对之前的数据进行处理返回一个新的数据给store

     if (action.type === 'add_todo_item') {
        const newState = JSON.parse(JSON.stringify(state));
    //把之前的输入的inputValue放到newState的列表当中
        newState.list.push(newState.inputValue);
    //同时清空输入框
        newState.inputValue = '';
        console.log(newState);
        return newState;
      }
    

    3.之前已经订阅了store,只要store改变store.subscribe()里的函数就会被执行

    constructor(props) {
          super(props);
          this.state = store.getState();
          this.handleStoreChange = this.handleStoreChange.bind(this);
          store.subscribe(this.handleStoreChange);
        }
    
     handleStoreChange(){
          // console.log('store changed');
    //当我感知到store的数据发生变化的时候,就调用store.getState()方法从store里面重新取一次数据,然后调用setState替换掉当前组件里的数据。
        this.setState(store.getState());
      }
    

    例3

    1.删除功能,在Todolist.js中list组件中添加删除方法

    <List
              style={{marginTop: '10px', width: '300px'}}
              bordered
              dataSource={this.state.list}
              renderItem={(item, index) => <List.Item onClick={this.bandleItemDelete.bind(this, index)}>{item}</List.Item>}
            />
    
     bandleItemDelete(index){
        const  action = {
          type:'delete_todo_item',
          index
        }
        store.dispatch(action);
      }
    

    2.reducer中

    if (action.type === 'delete_todo_item'){
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.splice(action.index, 1)//第一个参数值得是第几个,第二个参数指删除的数量
        return newState;
      }
    

    3.之前已经订阅了store,只要store改变store.subscribe()里的函数就会被执行

    constructor(props) {
          super(props);
          this.state = store.getState();
          this.handleStoreChange = this.handleStoreChange.bind(this);
          store.subscribe(this.handleStoreChange);
        }
    
     handleStoreChange(){
          // console.log('store changed');
    //当我感知到store的数据发生变化的时候,就调用store.getState()方法从store里面重新取一次数据,然后调用setState替换掉当前组件里的数据。
        this.setState(store.getState());
      }
    

    到这里就结束了。

    下面是页面完整代码:
    store文件夹下index.js代码

    import { createStore } from 'redux';
    import reducer from './reducer'
    
    const store = createStore(
      reducer,
       window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    );
    
    export default store;
    

    store文件夹下reducer.js代码:

    const defaultState = {
      inputValue:'123',
      list: [1,2]
    }
    //state指的是整个store里的数据
    export default (state = defaultState, action) => {
      if (action.type === 'change_input_value'){
    
        //对之前的state进行深拷贝
        const newState = JSON.parse(JSON.stringify(state));
        //让newState的inputValue等于新的传过来的新的value值
        newState.inputValue = action.value;
        return newState;
      }
      if (action.type === 'add_todo_item') {
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.push(newState.inputValue);
        newState.inputValue = '';
        console.log(newState);
        return newState;
      }
    if (action.type === 'delete_todo_item'){
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.splice(action.index, 1)
        return newState;
      }
      return state;
    }
    

    Todolist组件的代码:

    import React, {Component} from 'react';
    import 'antd/dist/antd.css';
    import { Button,List,Input } from 'antd';
    import store from './store/index';
    
    class TodoList extends Component{
        constructor(props) {
          super(props);
          this.state = store.getState();
          this.handleInputChange = this.handleInputChange.bind(this);
          this.handleStoreChange = this.handleStoreChange.bind(this);
          this.handleBtnClick = this.handleBtnClick.bind(this);
          store.subscribe(this.handleStoreChange);
        }
         render() {
           return (
               <div style={{margin:'10px'}}>
                  <div>
                    <Input
                      value={this.state.inputValue}
                      placeholder='todo info'
                      style={{width:'300px', marginRight:'10px'}}
                      onChange={this.handleInputChange}
                      />
                    <Button type="primary" onClick={this.handleBtnClick}>提交</Button>
                  </div>
                 <List
                   style={{marginTop:'10px',width:'300px'}}
                   bordered
                   dataSource={this.state.list}
                   renderItem={(item, index) => <List.Item onClick={this.bandleItemDelete.bind(this, index)}>{item}</List.Item>}
                 />
               </div>
           )
         }
    
      handleInputChange(e){
          const action = {
              type: 'change_input_value',
              value: e.target.value
          }
          store.dispatch(action);
          console.log(e.target.value);
      }
    
      handleStoreChange(){
          // console.log('store changed');
        this.setState(store.getState());
      }
    
      handleBtnClick(){
          const action = {
            type: 'add_todo_item'
          };
          store.dispatch(action);
      }
    bandleItemDelete(index){
        const  action = {
          type:'delete_todo_item',
          index
        }
        store.dispatch(action);
      }
    }
    
    export default TodoList;
    

    ActionTypes的拆分

    创建actionTypes.js ,

    export const CHANGE_INPUT_VALUE = 'change_input_value';
    export const ADD_TODO_ITEM = 'add_todo_item';
    export const DELETE_TODO_ITEM = 'delete_todo_item';
    

    到todolist和reducer中引入常量

    import {CHANGE_INPUT_VALUE,ADD_TODO_ITEM,DELETE_TODO_ITEM} from './store/actionTypes'
    
    import {CHANGE_INPUT_VALUE,ADD_TODO_ITEM,DELETE_TODO_ITEM} from './actionTypes'
    

    将所有所有type换成定义的 例如:

    handleInputChange(e){
        const action = {
          type:CHANGE_INPUT_VALUE,
          value:e.target.value
        }
        store.dispatch(action);
      }
    
    if (action.type === CHANGE_INPUT_VALUE){
        const newState = JSON.parse(JSON.stringify(state));
        newState.inputValue = action.value;
        return newState;
      }
    

    使用actionCreater统一创建action

    提高代码的可读性,方便自动化测试 。
    创建actionCreators.js

    import {CHANGE_INPUT_VALUE,ADD_TODO_ITEM,DELETE_TODO_ITEM} from './actionTypes'
    
    export const getInputChangeAction = (value)=>({
        type: CHANGE_INPUT_VALUE,
        value
    });
    export const getAddItemAction = () => ({
        type: ADD_TODO_ITEM,
    });
    export const getDeleteItemAction = (index)=>({
        type:DELETE_TODO_ITEM,
        index
    })
    

    Todolist.js中引入

    import {getInputChangeAction,getAddItemAction,getDeleteItemAction} from './store/actionCreators'
    
     handleInputChange(e){
        const action = getInputChangeAction(e.target.value);
        store.dispatch(action);
      }
     handleBtnChange(){
        const  action = getAddItemAction();
        store.dispatch(action);
      }
     bandleItemDelete(index){
        const action = getDeleteItemAction(index);
        store.dispatch(action);
      }
    

    相关文章

      网友评论

          本文标题:14.redux代码中使用19-05-15

          本文链接:https://www.haomeiwen.com/subject/vliuaqtx.html