react之redux(自学记录)

213 阅读3分钟

list组件

/*
 * @Author: your name
 * @Date: 2021-08-31 09:40:06
 * @LastEditTime: 2021-09-01 17:49:45
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /react/demo02/src/xiaojiejie.js
 */
import React, { Component, Fragment } from "react";
import "antd/dist/antd.css";
import { Input, Button, List } from "antd";
//相当于vue.use(vuex)注册全局,这个store是只在当前界面用
import store from "./store/index";

class TodoList extends Component {
  //js的构造函数,由于其他任何函数执行
  constructor(props) {
    super(props); //调用父类的构造函数,固定写法
    //相当于vue的data,但是此处是从仓库中获取的值
    this.state = store.getState();
    //订阅改变后的值
    this.storeChange = this.storeChange.bind(this);
    store.subscribe(this.storeChange);
    //绑定方法
    this.inputChange = this.inputChange.bind(this);
    this.clickBtn = this.clickBtn.bind(this);
  }
  render() {
    return (
      <Fragment>
        <div>
          <Input
            placeholder="请输入服务项目"
            style={{ width: "250px", margin: "10px 0" }}
            onChange={this.inputChange}
            value={this.state.inputValue}
          />
          <Button type="primary" onClick={this.clickBtn}>
            增加服务
          </Button>
        </div>

        <List
          bordered
          dataSource={this.state.list}
          renderItem={(item, index) => (
            // 此处第一个参数是this,第二个参数是index
            <List.Item onClick={this.deleteItem.bind(this, index)}>
              {item}
            </List.Item>
          )}
        />
      </Fragment>
    );
  }
  storeChange() {
    this.setState(store.getState());
  }
  inputChange(e) {
    const action = {
      type: "input_change",
      value: e.target.value,
    };
    store.dispatch(action);
  }
  clickBtn() {
    // this.setState({
    //   list: [...this.state.list, this.state.inputValue],
    // });
    const action = {
      type: "addItem",
    };
    store.dispatch(action);
  }
  deleteItem(index) {
    const action = {
      type: "deleteItem",
      index: index,
    };
    store.dispatch(action);
  }
}

export default TodoList;

redux

index
/*
 * @Author: your name
 * @Date: 2021-09-01 15:20:12
 * @LastEditTime: 2021-09-01 15:21:27
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /demo03/src/store/index.js
 */
//总出口
import { createStore } from "redux"; //  引入createStore方法
import reducer from "./reducer";
const store = createStore(reducer); // 创建数据存储仓库
export default store; //暴露出去

reducer
/*
 * @Author: your name
 * @Date: 2021-09-01 15:20:31
 * @LastEditTime: 2021-09-01 18:05:34
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /demo03/src/store/reducer.js
 */
//仓库
//store仓库是唯一的有且只能有一个,但是里面可以有多个state
//只有store能改变自己的内容,例如本例的reducer并不能改
//reducer必须是纯函数,返回的结果是传入的值决定的

const defaultState = {
  inputValue: "Write Something",
  list: ["早上4点起床,锻炼身体", "中午下班游泳一小时"],
};
//,加此处是为了解决打印提示不符合eslint的bug
//eslint-disable-next-line
export default (state = defaultState, action) => {
  //就是一个方法函数
  //state是原始仓库的状态,只是仓库,没有管理能力
  //action是action新的传递状态,管理能力
  if (action.type === "input_change") {
    let newState = JSON.parse(JSON.stringify(state));
    newState.inputValue = action.value;
    return newState;
  } else if (action.type === "addItem") {
    let newState = JSON.parse(JSON.stringify(state));
    newState.list.push(newState.inputValue);
    newState.inputValue = "";
    return newState;
  } else if (action.type === "deleteItem") {
    let newState = JSON.parse(JSON.stringify(state));
    newState.list.splice(action.index, 1);
    return newState;
  }
  return state;
};

ui与业务逻辑拆分

/*
 * @Author: your name
 * @Date: 2021-08-31 09:40:06
 * @LastEditTime: 2021-09-02 17:50:51
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /react/demo02/src/xiaojiejie.js
 */
import React, { Component, Fragment } from "react";

//相当于vue.use(vuex)注册全局,这个store是只在当前界面用
import store from "./store/index";
import TodoListUi from "../src/components/ItemChild";

class TodoList extends Component {
  //js的构造函数,由于其他任何函数执行
  constructor(props) {
    super(props); //调用父类的构造函数,固定写法
    //相当于vue的data,但是此处是从仓库中获取的值
    this.state = store.getState();

    //订阅改变后的值
    this.storeChange = this.storeChange.bind(this);
    store.subscribe(this.storeChange);
    //绑定方法
    this.inputChange = this.inputChange.bind(this);
    this.clickBtn = this.clickBtn.bind(this);
    this.deleteItem = this.deleteItem.bind(this);
  }
  render() {
    return (
      <Fragment>
        <TodoListUi
          inputValue={this.state.inputValue}
          list={this.state.list}
          inputChange={this.inputChange}
          clickBtn={this.clickBtn}
          deleteItem={this.deleteItem}
        ></TodoListUi>
      </Fragment>
    );
  }
  storeChange() {
    this.setState(store.getState());
  }
  inputChange(e) {
    const action = {
      type: "input_change",
      value: e.target.value,
    };
    store.dispatch(action);
  }
  clickBtn() {
    const action = {
      type: "addItem",
    };
    store.dispatch(action);
  }
  deleteItem(index) {
    const action = {
      type: "deleteItem",
      index: index,
    };
    store.dispatch(action);
  }
}

export default TodoList;

无状态子组件

/*
 * @Author: your name
 * @Date: 2021-08-31 09:41:39
 * @LastEditTime: 2021-09-02 17:56:26
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /react/demo02/src/components/Item.js
 */
import React, { Fragment } from "react";
import ProTypes from "prop-types";
import "antd/dist/antd.css";
import { Input, Button, List } from "antd";

// 首先我们不在需要引入React中的{ Component },删除就好。
// 然后些一个ItemChild函数,里边只返回JSX的部分就好,这步可以复制。
// 函数传递一个props参数,之后修改里边的所有props,去掉this


const ItemChild = (props) => {
  return (
    <Fragment>
      <div>
        <Input
          placeholder="请输入服务项目"
          style={{ width: "250px", margin: "10px 0" }}
          onChange={props.inputChange}
          value={props.inputValue}
        />
        <Button type="primary" onClick={props.clickBtn}>
          增加服务
        </Button>
      </div>

      <List
        bordered
        dataSource={props.list}
        renderItem={(item, index) => (
          <List.Item
            onClick={() => {
              this.props.deleteItem(index);
            }}
          >
            {item}
          </List.Item>
        )}
      />
    </Fragment>
  );
};
//注意,此处是小写
ItemChild.propTypes = {
  inputValue: ProTypes.string,
  list: ProTypes.array,
  inputChange: ProTypes.func,
  deleteItem: ProTypes.func,
  clickBtn: ProTypes.func,
};

export default ItemChild;