14. react 基础 redux 的编写 TodoList 功能
1. 安装 redux 监听工具 ( 需要翻墙 )
打开 谷歌商店
搜索 redux devtool
安装第一个即可
2. 安装 redux
yarn add redux
3. 创建 一个 store 文件夹( 与 项目 index.js 文件 同级 ) 并在 store 内 创建一个 reducer.js 文件 用于 区分各组件状态
# store/reducer.js
// 初始化 各组件的状态
const defaultState = {
inputValue : '', // 初始化 TodoList 的输入框的值
list : [] // 初始化 TodoList 列表的值
};
export default (state = defaultState, action)=>{
return state;
}
4. 在 store 文件夹内 创建 index.js 创建一个公共存储仓库, 将组件的各个状态作为参数传入
#store/index.js
import {createStore} from 'redux';
import reducer from './reducer'
const store = createStore(reducer);
export default store;
5. TodoList 内使用 store 进行数据存储
引入 store.js ( index.js 和 store 文件夹 是在同一级 )
import store from './store';
在 constructor 方法内 引入 store 的 state
constructor(props){
super(props);
this.state = store.getState(); // 当前 this.state 即可获得 store的 state 的内容
}
6. 当输入框改变时 改变 store 内的 inputValue 的数据
Input 添加 onChange 事件
# TodoList.js
<Input onChange={this.inputChange.bind(this)} />
inputChange(e){
// 调用 store.dispatch( action ) 方法 通知 store 变更 inputValue
const action = {
type : 'change_input_value',
value : e.target.value
};
store.dispatch( action );
}
# store 将 接收到的 state 和 action 转发给 reducer
# store/reducer.js
// reducer 可以接收 state 但是绝不可以修改 state
export default (state, action)=>{
// 打印 reducer 接收到的 state 和 action
console.log( state, action );
// 对 state 进行深复制 为 newState , 修改 newState 的值 并返回 newState
if( action.type === 'change_input_value' ){
const newState = JSON.parse( JSON.stringify( state ) );
newState.inputValue = action.value;
return newState;
}
return state;
}
# 当 store 返回数据发生了变化 需要 TodoList 订阅 store 数据变化 并进行 state 的 赋值
# TodoList.js
import store from './store'
constructor(){
// 订阅 store 的变化 并 编写 监听变化的 函数
store.subscribe(this.handStoreChange);
this.handStoreChange = this.handStoreChange.bind(this);
}
// 将 store 的值 重新 赋值给组件
handStoreChange(){
this.setState( store.getState() );
}
7. 同理 编写 列表 和 删除功能
#index.js
import React from 'react';
import ReactDOM from 'react-dom';
import TodoList from './TodoList';
ReactDOM.render(<TodoList />, document.getElementById('root'));
#TodoList.js
import React, { Component } from 'react';
import 'antd/dist/antd.css';
import { Input, Button, List } from 'antd';
import store from './store';
class TodoList extends Component{
constructor(props){
super(props);
this.state = store.getState();
this.inputValueChange = this.inputValueChange.bind(this);
this.addItem = this.addItem.bind(this);
this.delItem = this.delItem.bind(this);
this.handleStoreChange = this.handleStoreChange.bind(this);
store.subscribe(this.handleStoreChange);
}
render(){
return (
<div style={{ marginTop: '10px', marginLeft: '10px' }}>
<div>
<Input placeholder="请输入" value={this.state.inputValue} onChange={this.inputValueChange} style={{marginRight: '10px' , width: '300px'}} />
<Button type="primary" onClick={this.addItem}>提交</Button>
</div>
<div>
<List
style={{width: '300px', marginTop: '10px'}}
bordered
dataSource={this.state.list}
renderItem={(item, val)=> <List.Item index={val} onClick={this.delItem}>{item}</List.Item>}
/>
</div>
</div>
);
}
handleStoreChange(){
this.setState(store.getState());
}
addItem(){
const action = {
type: 'add_item',
value: this.state.inputValue
}
store.dispatch(action);
}
delItem(e){
const action = {
type : 'del_item',
value : e.target.getAttribute('index')
}
store.dispatch(action);
}
inputValueChange(e){
const action = {
type : 'input_value_change',
value : e.target.value
}
store.dispatch(action);
}
}
export default TodoList;
#store/index.js
import {createStore} from 'redux';
import reducer from './reducer';
const store = createStore(reducer);
export default store;
#store/reducer.js
const defaultState = {
inputValue : '',
list : []
}
export default (status = defaultState, action)=>{
console.log(status, action)
if(action.type === 'input_value_change'){
const newState = JSON.parse(JSON.stringify(status));
newState.inputValue = action.value;
return newState;
}
if(action.type === 'add_item'){
const newState = JSON.parse(JSON.stringify(status));
newState.list = [...newState.list, action.value];
newState.inputValue = '';
return newState;
}
if(action.type === 'del_item'){
const newState = JSON.parse(JSON.stringify(status));
newState.list.splice(action.value, 1);
return newState;
}
return status;
}
14. react 基础 redux 的编写 TodoList 功能的更多相关文章
- 4. react 基础 - 编写 todoList 功能
编写 TodoList 功能 react 入口 js #src/index.js import React from 'react'; import ReactDOM from 'react-dom' ...
- 13. react 基础 redux 的基本介绍 及 用 antd 编写 TodoList 的样式
1. redux 简述 当 store 内的 数据进行变更的时候 多个组件感知到 store 内的数据变化 将会被自动更新 2. redux 工作流 Store 代表数据存储 (例如: 图书馆管理 ...
- react native redux saga增加日志功能
redux-logger地址:https://github.com/evgenyrodionov/redux-logger 目前Reac native项目中已经使用redux功能,异步中间件使用red ...
- react用redux 做的todolist
### 1. 创建项目 create - react - app 项目名(shop) ### 2. 进入项目,下载redux cnpm install redux --save ### 3. ...
- (三)React基础
3-1 使用React编写TodoList功能 import { Fragment} from ‘react’ Fragment是占位符 用于替代最外层div元素, 防止生成的元素会有两层div嵌套这 ...
- 18 react react-redux 的编写 TodoList
1. 安装 react-redux yarn add react-redux 2. react-redux 编写 TodoList 使所有子组件 都能使用 store #index.js import ...
- 从0到1用react+antd+redux搭建一个开箱即用的企业级管理后台系列(基础篇)
背景 最近因为要做一个新的管理后台项目,新公司大部分是用vue写的,技术栈这块也是想切到react上面来,所以,这次从0到1重新搭建一个react项目架子,需要考虑的东西的很多,包括目录结构.代码 ...
- 最新的chart 聊天功能( webpack2 + react + router + redux + scss + nodejs + express + mysql + es6/7)
请表明转载链接: 我是一个喜欢捣腾的人,没事总喜欢学点新东西,可能现在用不到,但是不保证下一刻用不到. 我一直从事的是依赖angular.js 的web开发,但是我怎么能一直用它呢?看看最近火的一塌糊 ...
- 详解 Node + Redux + MongoDB 实现 Todolist
前言 为什么要使用 Redux? 组件化的开发思想解放了繁琐低效的 DOM 操作,以 React 来说,一切皆为状态,通过状态可以控制视图的变化,然后随着应用项目的规模的不断扩大和应用功能的不断丰富, ...
随机推荐
- 019、MySQL取本季度开始时间和本季度结束时间
SELECT QUARTER ( adddate( dy, ) ) QTR, date_add( dy, INTERVAL MONTH ) Q_start, adddate( dy, ) Q_end ...
- espcms P8.19082801 vulnerability
author: naiquan chai Net name:Hanamizuki花水木 Through the vulnerability we can get the webshell if w ...
- Codeforces Round #554 (Div. 2) 选做
C. Neko does Maths 题意 给 \(a,b\) ,求一个最小的 \(k\) 使得 \(\text{lcm}(a+k,b+k)\) 最小. \(a,b\le 10^9\) 题解 \(\g ...
- window 如何访问虚拟机的mapreduce(遇到的坑)
首先 先把你虚拟机和本机网络链接弄通 (详情看上一篇) 一些关于mapreduce 和hadoop的配置都在上一篇 安装eclipse 的hadoop Map/Reduce插件详情 看其他博客园.. ...
- Vue点到子路由,父级,无法高亮问题解决
[问题] Vue点到子路由,父级,无法高亮 [原因]多是因为链接简写相对路径没有写完整导致 [解决]把子路由的router-link的to属性里链接写完整.并把router配置文件里path也写完整即 ...
- 05 MySQL数据类型的选择与使用
数据类型的选择 1.CHAR与VARCHAR 存储/检索的方式不同. CHAR是固定长度,而VARCHAR是可变长度 非SQLMode下,超 ...
- OpenCV HOGDescriptor 参数图解
防止以后再次掉入坑中,决定还是在写写吧 OpenCV中的HOG特征提取功能使用了HOGDescriptor这个类来进行封装,其中也有现成的行人检测的接口.然而,无论是OpenCV官方说明文档还是各个中 ...
- netty权威指南学习笔记三——TCP粘包/拆包之粘包现象
TCP是个流协议,流没有一定界限.TCP底层不了解业务,他会根据TCP缓冲区的实际情况进行包划分,在业务上,一个业务完整的包,可能会被TCP底层拆分为多个包进行发送,也可能多个小包组合成一个大的数据包 ...
- C++面试常见问题——02动态分配内存
动态分配内存 C++动态内存 C++程序中内存分为两个部分 堆:程序中未使用的内存,在程序运行时可用于动态分配内存. 栈:函数内部申明的所有变量都将占用栈内存. 很多时候不知道一个程序到底需要多少内存 ...
- JPA#复杂查询#引子
_ 震惊....简历上写精通JPA的被下面几个问题震呆了.... 几个问题: 复杂查询如何从前端传递到后端,特别是多个条件的.且具有and和or等复杂逻辑,这个要如何封装呢? 多表查询? 自定义sql ...