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图片上下tab切换效果
Mar 18 Javascript
js Event对象的5种坐标
Sep 12 Javascript
javascript 二进制运算技巧解析
Nov 27 Javascript
JS中的this变量的使用介绍
Oct 21 Javascript
node.js中的fs.write方法使用说明
Dec 15 Javascript
利用JavaScript的AngularJS库制作电子名片的方法
Jun 18 Javascript
JS获取鼠标坐标位置实例分析
Jan 20 Javascript
jQuery Easyui Datagrid实现单行的上移下移及保存移动的结果
Aug 15 Javascript
基于cssSlidy.js插件实现响应式手机图片轮播效果
Aug 30 Javascript
jQuery点击页面其他部分隐藏下拉菜单功能
Nov 27 jQuery
使用element-ui的el-menu导航选中后刷新页面保持当前选中状态
Jul 19 Javascript
JavaScript字符串处理常见操作方法小结
Nov 15 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
Windows下的PHP5.0安装配制详解
2006/09/05 PHP
二十行语句实现从Excel到mysql的转化
2006/10/09 PHP
深入php self与$this的详解
2013/06/08 PHP
解析:php调用MsSQL存储过程使用内置RETVAL获取过程中的return值
2013/07/03 PHP
分享下php5类中三种数据类型的区别
2015/01/26 PHP
php实现两个数组相加的方法
2015/02/17 PHP
PHP怎样用正则抓取页面中的网址
2016/08/09 PHP
PHP给源代码加密的几种方法汇总(推荐)
2018/02/06 PHP
jQuery 1.4 15个你应该知道的新特性(译)
2010/01/24 Javascript
JQuery中根据属性或属性值获得元素(6种情况获取方法)
2013/01/17 Javascript
jQuery中:nth-child选择器用法实例
2014/12/31 Javascript
jQuery中$.each使用详解
2015/01/29 Javascript
js判断空对象的实例(超简单)
2016/07/26 Javascript
JS检测数组类型的方法小结
2017/03/14 Javascript
nodeJs实现基于连接池连接mysql的方法示例
2018/02/10 NodeJs
VUE2.0+ElementUI2.0表格el-table实现表头扩展el-tooltip
2018/11/30 Javascript
jquery+css3实现的经典弹出层效果示例
2020/05/16 jQuery
[44:15]DOTA2上海特级锦标赛主赛事日 - 5 败者组决赛Liquid VS EG第二局
2016/03/06 DOTA
Python HTML解析器BeautifulSoup用法实例详解【爬虫解析器】
2019/04/05 Python
Django 实现xadmin后台菜单改为中文
2019/11/15 Python
wxPython实现列表增删改查功能
2019/11/19 Python
Tensorflow 自定义loss的情况下初始化部分变量方式
2020/01/06 Python
python request 模块详细介绍
2020/11/10 Python
Selenium+BeautifulSoup+json获取Script标签内的json数据
2020/12/07 Python
python链表类中获取元素实例方法
2021/02/23 Python
CSS3按钮鼠标悬浮实现光圈效果源码
2016/09/11 HTML / CSS
美国创意礼品网站:UncommonGoods
2017/02/03 全球购物
Chicco婴儿用品美国官网:汽车座椅、婴儿推车、高脚椅等
2018/11/05 全球购物
北美主要的汽车零部件零售商:AutoShack.com
2019/02/23 全球购物
经典商业广告词
2014/03/13 职场文书
广播体操口号
2014/06/18 职场文书
优秀纪检干部材料
2014/08/27 职场文书
小学生作文批改评语
2014/12/25 职场文书
2015年建党94周年演讲稿
2015/03/19 职场文书
2015领导干部廉洁自律工作总结
2015/07/23 职场文书
七年级生物教学反思
2016/02/20 职场文书