react用Redux中央仓库实现一个todolist


Posted in Javascript onSeptember 29, 2019

本文实例为大家分享了react用Redux中央仓库实现一个todolist的具体代码,供大家参考,具体内容如下

react用Redux中央仓库实现一个todolist

Redux简单介绍

Redux是一个用来管理管理数据状态和UI状态的JavaScript应用工具。随着JavaScript单页应用(SPA)开发日趋复杂,JavaScript需要管理比任何时候都要多的state(状态),Redux就是降低管理难度的。(Redux支持React,Angular、jQuery甚至纯JavaScript)

Redux Dev Tools插件 Redux调试工具 谷歌商店下载

redux三个坑:

store仓库必须是唯一的,多个store是坚决不允许,只能有一个store空间

只有store能改变自己的内容,Reducer不能改变

Reducer必须是纯函数

Redux-thunk这个Redux最常用的插件:

在Dispatch一个Action之后,到达reducer之前,进行一些额外的操作,就需要用到middleware(中间件)

在实际工作中你可以使用中间件来进行日志记录、创建崩溃报告,调用异步接口或者路由

npm install --save redux-thunk

第一步 仓库 在store文件夹下新建index.js

//applyMiddleware,compose是为了使用下面两个插件
import {createStore,applyMiddleware,compose} from 'redux' //引入redux
import thunk from 'redux-thunk' //引入redux中间件插件
import reducer from './reducer'  //引用reducer中的数据
 
//浏览器安装的仓库插件 调试面板
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}):compose
 
//redux中间件插件 此函数为了兼容两个插件并行
const enhancer = composeEnhancers(applyMiddleware(thunk))
 
//定义一个仓库 唯一的 不能有两个仓库 createStore仓库只接收两个参数
const store = createStore( reducer, enhancer) // 创建数据存储仓库
export default store //将仓库导出

新建reducer.js 做仓库数据处理

import {ADD_ITEM , DELETE_ITEM , GET_LIST} from './actionTypes' //定义type类型的js文件
 
const defaultState = {
  value:'sss',
  list:[]  //后端获取的列表数据放在这里
}
 
// state: 指的是原始仓库里的状态。
// action: 指的是action新传递的状态。
export default (state = defaultState,action)=>{
  // console.log(state)
  //Reducer里只能接收state 不能改变state
  // if(action.type ==="changeInput"){
  //   let newState = JSON.parse(JSON.stringify(state)) //深拷贝state的值 转成字符串 赋值给一个变量
  //   newState.value = action.vlaue //改变placeholder的值等于用户输入的值
  //   return newState //将新state return出去
  // }
  //增加
  if(action.type === ADD_ITEM ){ //根据type值,编写业务逻辑
    let newState = JSON.parse(JSON.stringify(state)) 
    newState.list.push(action.value) //用户输入的新内容push新的内容到列表中去
    console.log(action)
    newState.value = '' //增加后清空
    return newState
  }
 
  //删除
  if(action.type === DELETE_ITEM ){ 
    let newState = JSON.parse(JSON.stringify(state)) 
    newState.list.splice(action.index,1) //删除数组中对应的值
    return newState
  }
 
   //后端获取数据 传递给中央仓库做处理
   if(action.type === GET_LIST ){ 
    let newState = JSON.parse(JSON.stringify(state)) 
    newState.list =action.data
    return newState
  }
  return state
}

actionTypes.js   集中管理页面reducer的type类型

//集中管理页面reducer的type类型
 
export const ADD_ITEM = "addItem"  //定义常量一般用大写
export const DELETE_ITEM = "deleteItem" 
export const GET_LIST = "getListAction"

actionCreators.js  封装组件的action

//封装组件的action
import {ADD_ITEM , DELETE_ITEM ,GET_LIST} from './actionTypes' //定义type类型的js
import axios from 'axios'
 
//组件addItem里的action type已经封好 所以把value作为参数用箭头函数(value)=>传进来即可 
 
//增加数据
export const addItem = (value)=>({
  type:ADD_ITEM,
  value
})
 
//删除数据
export const deleteItem = (index)=>({
  type:DELETE_ITEM,
  index
})
 
//获取数据
export const getListAction = (data)=>({
  type:GET_LIST,
  data
})
 
export const getTodoList = () =>{
  return (dispatch)=>{
    axios.get('https://www.easy-mock.com/mock/5d63d7ca5774121e1a634378/demo1/demo1') 
    .then((res)=>
    {
      const data = res.data.data;
      const action = getListAction(data)
      dispatch(action)  //将action这个值传给仓库
    })
    .catch((error)=>{
      console.log(error)
    })
  }
}

TodoList.js  组件js部分

import React, { Component } from 'react';
import TodoListUi from './TodoListUi' //组件UI部分
import store from '../store/index' //组件中获得store中的数据
//import {ADD_ITEM , DELETE_ITEM} from '../store/actionTypes' //定义type类型的js 为了更方便检查错误 写错会报错
import { addItem,deleteItem,getTodoList } from '../store/actionCreators' //封装的action
 
 
//用reducer写todolist 调用中央仓库
 
class TodoList extends Component {
  constructor(props){
    super(props)
    // console.log(store.getState()) //getState方法取出仓库的值
    this.state = store.getState() //将组件state数据赋值给仓库数据
    this.changeInputVlaue = this.changeInputVlaue.bind(this) //给方法做this绑定
    this.storeChange = this.storeChange.bind(this)
    this.clickBtn = this.clickBtn.bind(this)
    this.deleteItem = this.deleteItem.bind(this)
    store.subscribe(this.storeChange) //订阅模式 改变数据时同步让仓库中的数据改变
  }
  render() { 
    return ( 
      <TodoListUi
        value={this.state.value}
        changeInputVlaue={this.changeInputVlaue}
        clickBtn={this.clickBtn}
        list={this.state.list}
        deleteItem = {this.deleteItem}
      ></TodoListUi>
     );
  }
 
  componentDidMount(){
    // axios.get('https://www.easy-mock.com/mock/5d63d7ca5774121e1a634378/demo1/demo1') 
    //   .then((res)=>
    //   {
    //    const data = res.data.data;
    //    const action =getListAction(data) //将取到的数据封入action
    //    store.dispatch(action) //传递给reducer
    //   })
    //   .catch((error)=>{
    //     console.log(error)
    //   })
    const action = getTodoList() //使用中间件获取数据
    store.dispatch(action) //传给仓库
  }
  //用户输入的值传给仓库 要通过dispatch()方法传递给store
  //Action就是一个对象,这个对象一般有两个属性,第一个是对Action的描述,第二个是要改变的值。
  //之前注销的方法,在reducer里深拷贝完state里面的数据,无法同步将用户输入赋值给state
  changeInputVlaue(e){
    this.setState({
      value:e.target.value //将用户输入的value绑定给仓库中的value,监听用户输入
    })
    // const action = {
    //   type:'changeInput', // 名字
    //   value:e.target.value //值
    // }
    // store.dispatch(action)
  }
 
  //state和组件的值同步互相改变
  storeChange(){
    this.setState(store.getState()) 
  }
 
  //增加 因为list数据存在中央仓库里 所以要做的是 将组件数据传给仓库 改变仓库数据后 再返回给组件展示
  clickBtn(){
    // console.log(this.state.value)
    // const action = { 
    //   type:ADD_ITEM,
    //   value:this.state.value //获取到用户value,用于push
    // }
    const action = addItem(this.state.value);
    store.dispatch(action)
  }
  //删除
  deleteItem(index){
    // console.log(index)
    // const action = {
    //   type:DELETE_ITEM,
    //   index  //index传过去用于删除
    // }
    const action =deleteItem(index)
    store.dispatch(action)
  }
}
export default TodoList;

TodoListUi.js 组件UI部分抽离成子组件

//此文件用于视图和逻辑的分离
import React from 'react';
import 'antd/dist/antd.css'  //引入Ant Design UI库
import { Input ,Button,List} from 'antd'  //引入input组件
 
//无状态组件 提高性能 将组件改造成函数
const TodoListUi = (props)=>{
  return ( 
    <div style={{margin:"100px"}}>
      <div>
        <Input
        style={{ width:"250px",marginRight:"20px"}}
        onChange={props.changeInputVlaue}
        value={props.value}
        />
        <Button type='primary' onClick={props.clickBtn}>增加</Button>
      </div>
      <div style={{margin:"10px",width:"300px"}}>
      <List
          bordered //加边框
          dataSource={props.list} //渲染什么数据
          renderItem={(item,index)=>(<List.Item onClick={()=>{props.deleteItem(index)}}>{item}</List.Item>)} //每项
        /> 
      </div>
    </div>
   );
}
 
//改造前组件 上边需要从react引入Component
// class TodoListUi extends Component {
//   state = { }
//   render() { 
//     return ( 
//       <div style={{margin:"100px"}}>
//         <div>
//           <Input
//           style={{ width:"250px",marginRight:"20px"}}
//           onChange={this.props.changeInputVlaue}
//           value={this.props.value}
//           />
//           <Button type='primary' onClick={this.props.clickBtn}>增加</Button>
//         </div>
//         <div style={{margin:"10px",width:"300px"}}>
//         <List
//             bordered //加边框
//             dataSource={this.props.list} //渲染什么数据
//             renderItem={(item,index)=>(<List.Item onClick={()=>{this.props.deleteItem(index)}}>{item}</List.Item>)} //每项
//           /> 
//         </div>
//       </div>
//     );
//   }
// }
 
export default TodoListUi;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery中需要注意的细节问题小结
Dec 06 Javascript
js自定义事件及事件交互原理概述(二)
Feb 01 Javascript
火狐textarea输入法的bug的触发及解决
Jul 24 Javascript
javascript实现自动填写表单实例简析
Dec 02 Javascript
JavaScript中三种异步上传文件方式
Mar 06 Javascript
js和C# 时间日期格式转换的简单实例
May 28 Javascript
老生常谈javascript的类型转换
Oct 12 Javascript
获取当前按钮或者html的ID名称实例(推荐)
Jun 23 Javascript
JavaScript模拟实现封装的三种方式及写法区别
Oct 27 Javascript
手动用webpack搭建第一个ReactApp的示例
Apr 11 Javascript
详解从0开始搭建微信小程序(前后端)的全过程
Apr 15 Javascript
如何使用Javascript中的this关键字
May 28 Javascript
layui数据表格 table.render 报错的解决方法
Sep 29 #Javascript
JavaScript实现秒杀时钟倒计时
Sep 29 #Javascript
在layui中对table中的数据进行判断(0、1)转换为提示信息的方法
Sep 28 #Javascript
layui+jquery支持IE8的表格分页方法
Sep 28 #jQuery
JavaScript获取页面元素的常用方法详解
Sep 28 #Javascript
解决Layui数据表格的宽高问题
Sep 28 #Javascript
解决layui-table单元格设置为百分比在ie8下不能自适应的问题
Sep 28 #Javascript
You might like
解决控件遮挡问题:关于有窗口元素和无窗口元素
2007/01/28 PHP
php的crc32函数使用时需要注意的问题(不然就是坑)
2015/04/21 PHP
Javascript 通过json自动生成Dom的代码
2010/04/01 Javascript
基于JavaScript 声明全局变量的三种方式详解
2013/05/07 Javascript
jquery 实现窗口的最大化不论什么情况
2013/09/03 Javascript
ExtJS4如何自动生成控制grid的列显示、隐藏的checkbox
2014/05/02 Javascript
全面解析JavaScript里的循环方法之forEach,for-in,for-of
2020/04/20 Javascript
用自定义图片代替原生checkbox实现全选,删除以及提交的方法
2016/10/18 Javascript
JavaScript省市级联下拉菜单实例
2017/02/14 Javascript
微信小程序 本地图片按照屏幕尺寸处理
2017/08/04 Javascript
vue数字类型过滤器的示例代码
2017/09/07 Javascript
JavaScript继承定义与用法实践分析
2018/05/28 Javascript
vue.js使用v-if实现显示与隐藏功能示例
2018/07/06 Javascript
vue 纯js监听滚动条到底部的实例讲解
2018/09/03 Javascript
微信小程序利用swiper+css实现购物车商品删除功能
2019/03/06 Javascript
js微信分享接口调用详解
2019/07/23 Javascript
超详细的5个Shell脚本实例分享(值得收藏)
2019/08/15 Javascript
[01:03:38]2014 DOTA2国际邀请赛中国区预选赛5.21 CNB VS CIS
2014/05/22 DOTA
PYTHON正则表达式 re模块使用说明
2011/05/19 Python
在Python的Flask框架中使用模版的入门教程
2015/04/20 Python
Django查找网站项目根目录和对正则表达式的支持
2015/07/15 Python
Python实现简单的代理服务器
2015/07/25 Python
python中使用正则表达式的后向搜索肯定模式(推荐)
2017/11/11 Python
python基础之包的导入和__init__.py的介绍
2018/01/08 Python
Python用for循环实现九九乘法表
2018/05/31 Python
python 循环数据赋值实例
2019/12/02 Python
python读取配置文件方式(ini、yaml、xml)
2020/04/09 Python
简单了解python列表和元组的区别
2020/05/14 Python
python退出循环的方法
2020/06/18 Python
浅析HTML5中的download属性使用
2019/03/13 HTML / CSS
英国在线照明超市:Castlegate Lights
2019/10/30 全球购物
文秘档案管理岗位职责
2014/03/06 职场文书
小学班主任评语大全
2014/04/23 职场文书
上课讲话检讨书范文
2015/05/07 职场文书
什么是执行力?9个故事告诉您:成功绝非偶然!
2019/07/05 职场文书
python中pycryto实现数据加密
2022/04/29 Python