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 表格分页等操作实现代码(pagedown,pageup)
Apr 11 Javascript
Javascript获取CSS伪元素属性的实现代码
Sep 28 Javascript
简介JavaScript中POSITIVE_INFINITY值的使用
Jun 05 Javascript
谈谈对JavaScript原生拖放的深入理解
Sep 20 Javascript
微信小程序 Image API实例详解
Sep 30 Javascript
JQuery实现文字无缝滚动效果示例代码(Marquee插件)
Mar 07 Javascript
JavaScript实现获取用户单击body中所有A标签内容的方法
Jun 05 Javascript
JS实现搜索关键词的智能提示功能
Jul 07 Javascript
vue检测对象和数组的变化分析
Jun 30 Javascript
node app 打包工具pkg的具体使用
Jan 17 Javascript
浏览器事件循环与vue nextTicket的实现
Apr 16 Javascript
JavaScript WeakMap使用详解
Feb 05 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的网址
2006/11/25 PHP
Smarty中调用FCKeditor的方法
2014/10/27 PHP
PHP函数func_num_args用法实例分析
2015/12/07 PHP
基于php实现的验证码小程序
2016/12/13 PHP
javascript权威指南 学习笔记之null和undefined
2011/09/25 Javascript
JavaScript学习笔记(一) js基本语法
2011/10/25 Javascript
JQuery select(下拉框)操作方法汇总
2015/04/15 Javascript
jQuery插件Slider Revolution实现响应动画滑动图片切换效果
2015/06/05 Javascript
js replace()去除代码中空格的实例
2017/02/14 Javascript
jQuery插件FusionCharts实现的Marimekko图效果示例【附demo源码】
2017/03/24 jQuery
基于JS实现仿京东搜索栏随滑动透明度渐变效果
2017/07/10 Javascript
vue发送ajax请求详解
2018/10/09 Javascript
利用Vue-draggable组件实现Vue项目中表格内容的拖拽排序
2019/06/07 Javascript
微信小程序动画组件使用解析,类似vue,且更强大
2019/08/01 Javascript
用原生JS实现爱奇艺首页导航栏代码实例
2019/09/19 Javascript
vue 解除鼠标的监听事件的方法
2019/11/13 Javascript
JavaScript面试中常考的字符串操作方法大全(包含ES6)
2020/05/10 Javascript
Python单例模式实例分析
2015/01/14 Python
Python使用matplotlib绘制动画的方法
2015/05/20 Python
利用Python抓取行政区划码的方法
2016/11/28 Python
python通过百度地图API获取某地址的经纬度详解
2018/01/28 Python
TensorFlow模型保存/载入的两种方法
2018/03/08 Python
python实现顺序表的简单代码
2018/09/28 Python
python调用pyaudio使用麦克风录制wav声音文件的教程
2019/06/26 Python
django数据关系一对多、多对多模型、自关联的建立
2019/07/24 Python
Python学习笔记之For循环用法详解
2019/08/14 Python
Python替换NumPy数组中大于某个值的所有元素实例
2020/06/08 Python
HTML5 Canvas像素处理使用接口介绍
2012/12/02 HTML / CSS
HTML5中的进度条progress元素简介及兼容性处理
2016/06/02 HTML / CSS
英国亚马逊官方网站:Amazon.co.uk
2019/08/09 全球购物
2014年小学植树节活动方案
2014/03/02 职场文书
2014全国两会学习心得体会1000字
2014/03/10 职场文书
医学专业大学生职业生涯规划书
2014/10/25 职场文书
乌镇导游词
2015/02/02 职场文书
总账会计岗位职责
2015/04/02 职场文书
apache ftpserver搭建ftp服务器
2022/05/20 Servers