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 相关文章推荐
javascript制作loading动画效果 loading效果
Jan 14 Javascript
javascript操作referer详细解析
Mar 10 Javascript
jQuery提交多个表单的小技巧
Jul 27 Javascript
js实现简单的联动菜单效果
Aug 19 Javascript
jQuery同步提交示例代码
Dec 12 Javascript
jQuery控制控件文本的长度的操作方法
Dec 05 Javascript
原生JS实现在线问卷调查投票特效
Jan 03 Javascript
Vue.js学习之过滤器详解
Jan 22 Javascript
基于滚动条位置判断的简单实例
Dec 14 Javascript
微信小程序scroll-view横向滑动嵌套for循环的示例代码
Sep 20 Javascript
vue组件文档(.md)中如何自动导入示例(.vue)详解
Jan 25 Javascript
详细介绍解决vue和jsp结合的方法
Feb 06 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
无数据库的详细域名查询程序PHP版(2)
2006/10/09 PHP
php防止SQL注入详解及防范
2013/11/12 PHP
PHP使用imagick读取PDF生成png缩略图的两种方法
2014/03/20 PHP
我整理的PHP 7.0主要新特性
2016/01/07 PHP
php中替换字符串函数strtr()和str_repalce()的用法与区别
2016/11/25 PHP
php使用ftp实现文件上传与下载功能
2017/07/21 PHP
Extjs学习笔记之三 extjs form更多的表单项
2010/01/07 Javascript
JavaScript 盒模型 尺寸深入理解
2012/12/31 Javascript
jQuery中使用Ajax获取JSON格式数据示例代码
2013/11/26 Javascript
js实现鼠标悬停图片上时滚动文字说明的方法
2015/02/17 Javascript
js实现可键盘控制的简单抽奖程序
2016/07/13 Javascript
详解JavaScript中数组的reduce方法
2016/12/02 Javascript
echarts饼图扇区添加点击事件的实例
2017/10/16 Javascript
实现单层json按照key字母顺序排序的示例
2017/12/06 Javascript
Nodejs中使用puppeteer控制浏览器中视频播放功能
2019/08/26 NodeJs
解决Layui当中的导航条动态添加后渲染失败的问题
2019/09/25 Javascript
js实现自动播放匀速轮播图
2020/02/06 Javascript
使用vue实现HTML页面生成图片的方法
2020/03/12 Javascript
详解vite+ts快速搭建vue3项目以及介绍相关特性
2021/02/25 Vue.js
简单的Python的curses库使用教程
2015/04/11 Python
python的dataframe和matrix的互换方法
2018/04/11 Python
Python实现简单http服务器
2018/04/12 Python
Python字符串的一些操作方法总结
2019/06/10 Python
django云端留言板实例详解
2019/07/22 Python
tensorflow的计算图总结
2020/01/12 Python
python Canny边缘检测算法的实现
2020/04/24 Python
Python高并发和多线程有什么关系
2020/11/14 Python
美国肌肉和力量商店:Muscle & Strength
2019/06/22 全球购物
西班牙最好的在线购买葡萄酒的商店:Vinoseleccion
2019/10/30 全球购物
岗位廉洁从政承诺书
2014/03/27 职场文书
帮一个朋友写的求职信
2014/08/09 职场文书
房屋鉴定委托书范本
2014/09/23 职场文书
再读《皇帝的新衣》的读后感悟!
2019/08/07 职场文书
浅谈JS和Nodejs中的事件驱动
2021/05/05 NodeJs
Python实现GIF动图以及视频卡通化详解
2021/12/06 Python
vue自定义右键菜单之全局实现
2022/04/09 Vue.js