Redux

1、UI 组件和容器组件

UI 组件负责容器的渲染,容器组件负责页面的逻辑 ;

将之前的 TodoList.js 拆分成 UI 组件和容器组件,

TodoListUI.js :

import React, { Component } from 'react';
import { Input, Button, List } from 'antd';

class TodoListUI extends Component {
  render() {
    return (
      <div style={{marginTop: '10px', marginLeft: '10px'}}>
        <div>
          <Input
            placeholder="todo info"
            style={{width: '300px', marginRight: '10px'}}
            value = {this.props.inputValue}
            onChange={this.props.handleInputChange}
          />
          <Button
            type="primary"
            onClick={this.props.handleBtnClick}
          >
            提交
          </Button>
        </div>
        <List
          style={{marginTop: '10px', width: '300px'}}
          bordered
          dataSource={this.props.list}
          renderItem={
            (item, index) => <List.Item onClick={(index) => this.props.handleDeleteItem(index)}> {item}</List.Item>
          }
        />
      </div>
    )
  }handleDeleteItem
}

export default TodoListUI;

TodoList.js :

import React, { Component } from 'react';
import 'antd/dist/antd.css';

import store from './store/index';  //引入store
import { getHandleInputChangeAction, getHandleBtnClick, getHandleDeleteItem } from './store/actionCreators';
import TodoListUI from './TodoListUI';

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);
    this.handleDeleteItem=this.handleDeleteItem.bind(this);
    store.subscribe(this.handleStoreChange);  //只要store发生改变就执行handleStoreChange这个函数
  }
  render() {
    return (
      <TodoListUI 
        inputValue={this.state.inputValue}
        handleInputChange={this.handleInputChange}
        handleBtnClick={this.handleBtnClick}
        handleDeleteItem={this.handleDeleteItem}
        list={this.state.list}
      />
    )
  }
  handleInputChange(e) {
    const action = getHandleInputChangeAction(e.target.value);
    store.dispatch(action);
  }
  handleStoreChange() {
    this.setState(store.getState());  //当我感知到store的数据发生变化的时候,就去调用store.getState方法,从store里重新取一次数据,然后通过this.setState替换掉当前组件的数据
  }
  handleBtnClick() {
    const action = getHandleBtnClick();
    store.dispatch(action);
  }
  handleDeleteItem(index) {
    const action = getHandleDeleteItem(index);
    store.dispatch(action);
  }
}

export default TodoList;

2、无状态组件

当我们一个组件只有 render 函数的时候,就可以用一个无状态组件来定义它。

优势:它的性能比较高,因为它就是一个函数,而之前的 TodoListUI 是一个类,类生成对象的过程中需要经过一些生命周期函数,它执行的东西远比执行一个函数要多得多。

使用场景:一般用在 UI 组件中 。

TodoListUI.js :

import React from 'react';
import { Input, Button, List } from 'antd';

//无状态组件
const TodoListUI = (props) => {
  return (
    <div style={{marginTop: '10px', marginLeft: '10px'}}>
      <div>
        <Input
          placeholder="todo info"
          style={{width: '300px', marginRight: '10px'}}
          value = {props.inputValue}
          onChange={props.handleInputChange}
        />
        <Button
          type="primary"
          onClick={props.handleBtnClick}
        >
          提交
        </Button>
      </div>
      <List
        style={{marginTop: '10px', width: '300px'}}
        bordered
        dataSource={props.list}
        renderItem={
          (item, index) => <List.Item onClick={(index) => props.handleDeleteItem(index)}> {item}</List.Item>
        }
      />
    </div>
  )
}

export default TodoListUI;

3、Redux 中发送异步请求获取数据

mockdata.js :

import Mock from 'mockjs';

const data = ['吃饭', '睡觉', '大幺幺'];

Mock.mock('/list', {
  data
})

TodoList.js 引入 mockjs 后添加异步请求代码:

  componentDidMount() {
    axios.get('/list')
      .then(res => {
        const data = res.data.data;
        const action = getAjaxData(data);
        store.dispatch(action);
      });
  }

接着给添加 redux 中的代码,告诉 store 将 data 赋值给 list ,这样一开始的 item 显示的就是 ajax 获取的数据了。

 


4、 使用 Redux-thunk 中间件实现 ajax 数据请求 ;

redux-thunk 这个中间件可以使我们把复杂的逻辑移到 action 中去管理。

同时用两个以上的中间件时 应该这个定义store ,store 下的 index.js :

/*创建一个store*/
import { createStore, applyMiddleware, compose } from 'redux';  //引入createStore
import reducer from './reducer';
import thunk from 'redux-thunk';

//同时用两个以上的中间件
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;

const enhancer = composeEnhancers(
  applyMiddleware(thunk),
);

const store = createStore( reducer, enhancer );

export default store;

actionCreators.js :

import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM, AJAX_DATA } from './actionTypes';
import axios from 'axios';

export const getHandleInputChangeAction = (value) => ({
  type: CHANGE_INPUT_VALUE,
  value
})
export const getHandleBtnClick = () => ({
  type: ADD_TODO_ITEM
})
export const getHandleDeleteItem = (index) => ({
  type: DELETE_TODO_ITEM,
  index
})
export const getAjaxData = (data) => ({
  type: AJAX_DATA,
  data
})
//异步请求
export const getTodoList = () => {
  //使用了 redux-thunk 后就能返回一个函数
  return (dispatch) => {
    axios.get('/list')
      .then(res => {
        const data = res.data.data;
        const action = getAjaxData(data);
        dispatch(action);
      });
  }
}

TodoList.js :

  componentDidMount() {
    const action = getTodoList();
    store.dispatch(action);  //当store判断到action不是一个对象的时候,它就会去执行action这个函数
  }

5、什么是Redux 中间件

        中间指的是 action 和 store 之间,实际上中间件就是对 dispatch 方法的一个封装,最原始的 dispatch 方法接收到一个对象之后就会把这个对象传递给 store ,这个就是没有中间件的情况。

        当我们对 dispatch 方法做了一个升级之后,比如说使用了 redux-thunk ,此时调用 dispatch 方法,给 dispatch 方法传递的是一个对象的话,那么这个 dispatch 方法又会把这个对象直接传给 store ,这和原始的 dispatch 方法没有区别。假设传递的是一个函数的话,他不会把这个函数直接传递给 store ,他会让这个函数先执行,执行完了之后这个函数再去调用 store 。

 


6、Redux-saga中间件使用入门

redux-saga 和 redux-thunk 一样,都是处理复杂的逻辑或者异步操作。

saga 一般都会单独创建一个 js 文件来管理。

有了 redux-saga 之后,除了在 reducer 里面可以接收 action ,saga.js 也能接收 action 。

  • 目录结构

  • TodoList.js 
  componentDidMount() {  //给sage发action
    const action = getInitialData();
    store.dispatch(action);
  }
  • sage.js 
import { takeEvery, put } from 'redux-saga/effects'; 
import { GET_INITIAL_DATA } from './actionTypes';
import { getAjaxData } from './actionCreator';
import axios from 'axios';
//put 就是来代替store.dispatch方法的
//takeEvery 是 redux-saga提供的一个方法
function* getInitialData() {
  try {
    const res = yield axios.get('/list');
    const action = getAjaxData(res.data.data);
    yield put(action);
  } catch(e) {
    console.log('网络请求失败');
  }
}
function* mySaga() {
  yield takeEvery(GET_INITIAL_DATA, getInitialData);
  //意思就是只要捕捉到GET_INITIAL_DATA这个action类型,就去执行getInitialData这个方法
}

export default mySaga;

此时就能正常地获取数据了。

 


7、React-Redux 的使用

React-Redux 是一个第三方的模块,可以帮助我们在 React 中更方便地使用 Redux 。

无状态组件可以有效地提升代码的性能,因为里面没有任何的生命周期函数,同时也不会生成真正的组件实例。

  • 项目目录结构:

  • TodoList.js:
import React from 'react';
import 'antd/dist/antd.css';
import { Input, Button, List } from 'antd';
import { connect } from 'react-redux';  //因为index.js中的Provider将store做了连接,使内部的组件都能很方便地获取store。就是通过connect这个方法来获取store里面地数据的
import { getChangeInputValue, getAddItem, getDelItem } from './store/actionCreater';

const TodoList = (props) => {
  const { inputValue, list, changeInputValue, handleClick, handleDeleteItem } = props;
  return (
    <div style={{ textAlign: "center" }}>
      <Input
        placeholder="Basic usage"
        style={{ width: 300, margin: 10 }}
        value={inputValue}
        onChange={changeInputValue}
      />
      <Button
        type="primary"
        onClick={handleClick}
      >
        提交
      </Button>
      <List
        style={{ width: 400, textAlign: "center", margin: '10px auto' }}
        bordered
        dataSource={list}
        renderItem={item => <List.Item onClick={handleDeleteItem.bind(this, item.id)}>{item.content}</List.Item>}
      />
    </div>
  )
}

const mapStateToProps = (state) => {  //state是store里面的数据
  return {
    inputValue: state.inputValue,
    list: state.list
  }
}

const mapDispatchToProps = (dispatch) => {  //对store的数据做修改
  return {
    changeInputValue(e) {
      const action = getChangeInputValue(e.target.value);
      dispatch(action);
    },
    handleClick() {
      const action = getAddItem();
      dispatch(action);
    },
    handleDeleteItem(id) {
      const action = getDelItem(id);
      dispatch(action);
    }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoList);  //意思就是让我的todolist这个组件和store做连接, 连接规则在 mapStateToProps 里面
//之前我们都是直接导出 TodoList 这个组件,现在我们导出的是connect这个方法。可以这么理解:现在 TodoList是一个UI组件,当我们用connect把这个UI组件做一些业务逻辑相结合的时候,然会的内容实际上就是一个容器组件。
  • index.js :
import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList';
import { Provider } from 'react-redux';
import store from './store/index';

const App = (
  <Provider store={store}>  {/*其实 Provider 就是一个组件,Provider意思就是我连接了store,那么Provider里面所有的组件就有能力获取到store里面的内容了*/}
    <TodoList />
  </Provider>
)


ReactDOM.render(App, document.getElementById('root'));

别的文件内容和之前相同。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
辽B代驾管理系统对代驾订单管理、用户咨询管理、代驾订单评价管理、代驾订单投诉管理、字典管理、论坛管理、公告管理、新闻信息管理、司机管理、用户管理、管理员管理等进行集中化处理。经过前面自己查阅的网络知识,加上自己在学校课堂上学习的知识,决定开发系统选择小程序模式这种高效率的模式完成系统功能开发。这种模式让操作员基于浏览器的方式进行网站访问,采用的主流的Java语言这种面向对象的语言进行辽B代驾管理系统程序的开发,在数据库的选择上面,选择功能强大的Mysql数据库进行数据的存放操作。辽B代驾管理系统的开发让用户查看代驾订单信息变得容易,让管理员高效管理代驾订单信息。 辽B代驾管理系统具有管理员角色,用户角色,这几个操作权限。 辽B代驾管理系统针对管理员设置的功能有:添加并管理各种类型信息,管理用户账户信息,管理代驾订单信息,管理公告信息等内容。 辽B代驾管理系统针对用户设置的功能有:查看并修改个人信息,查看代驾订单信息,查看公告信息等内容。 辽B代驾管理系统针对管理员设置的功能有:添加并管理各种类型信息,管理用户账户信息,管理代驾订单信息,管理公告信息等内容。 辽B代驾管理系统针对用户设置的功能有:查看并修改个人信息,查看代驾订单信息,查看公告信息等内容。 系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。项目管理页面提供的功能操作有:查看代驾订单,删除代驾订单操作,新增代驾订单操作,修改代驾订单操作。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。新闻管理页面,此页面提供给管理员的功能有:新增新闻,修改新闻,删除新闻。新闻类型管理页面,此页面提供给管理员的功能有:新增新闻类型,修改新闻类型,删除新闻类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值