1、概念
- react只是一个轻量级的视图层框架,如果要做大型应用就要搭配视图层框架redux一起使用
- redux组件之间的传值非常简单,redux里面要求我们把数据都放在一个公共的存储区域store里面,组件之中尽量少放数据,也就是所有数据都不放在组件自身了,都把它放到一个公用的存储空间里面,然后组件改变数据就不需要传递了,改变store里面的数据之后其它的组件会感知到里面的数据发生改变。这样的话不管组件的层次有多深,但是走的流程都是一样的,会把数据的传递简化很多。
2、Redux的工作流程
3、使用Ant Design实现TodoList页面布局
ant design https://ant.design/docs/react/introduce-cn
- yarn add antd
- demo如下:
import React,{Component} from 'react';
import { Input,Button,List } from 'antd';
import 'antd/dist/antd.css';
const data = [
'Racing car sprays burning fuel into crowd.',
'Japanese princess to wed commoner.',
'Australian walks 100km after outback crash.',
'Man charged over missing wedding girl.',
'Los Angeles battles huge wildfires.',
];
class TodoList extends Component {
render(){
return (<div>
<Input placeholder="Basic usage" style={
{width:'300px',marginLeft:'10px',marginTop:'10px'}} />
<Button type="primary" style={
{marginLeft:'10px',marginTop:'10px'}} >Primary</Button>,
<List style={
{marginLeft:'10px',marginTop:'10px',width:'300px'}}
bordered
dataSource={data}
renderItem={item => (
<List.Item>
{item}
</List.Item>
)}
/>
</div>
);
}
}
export default TodoList;
4、创建store
- yarn add redux
- demo code
import {createStore} from 'redux';
import reducer from './reducer';
const store = createStore(reducer);
export default store;
代码语言:javascript复制const defaultState = {
inputValue: '123',
list: [1,2]
}
export default (state=defaultState, action)=>{
return state;
}
代码语言:javascript复制import React,{Component} from 'react';
import { Input,Button,List } from 'antd';
import store from './store/';
import 'antd/dist/antd.css';
class TodoList extends Component {
constructor(props) {
super(props);
this.state = store.getState();
console.log(this.state);
}
render(){
const {inputValue,list} = this.state;
return (<div>
<Input placeholder={inputValue} style={
{width:'300px',marginLeft:'10px',marginTop:'10px'}} />
<Button type="primary" style={
{marginLeft:'10px',marginTop:'10px'}} >Primary</Button>,
<List style={
{marginLeft:'10px',marginTop:'10px',width:'300px'}}
bordered
dataSource={list}
renderItem={item => (
<List.Item>
{item}
</List.Item>
)}
/>
</div>
);
}
}
export default TodoList;
5、Action和Reducer的编写,TodoList增删
谷歌访问助手——https://github.com/haotian-wang/google-access-helper 1)要想更新state中的数据,首先派发一个action,action通过dispatch方法传给store。 2)store把之前的数据previousState和传过来的action转发给reducers函数。 3)reducers接收state和action后进行数据处理,重新生成一个newState(原state只读不改),把newState作为返回值返回给store。 4)store接收newState,将新数据替换原来的数据。 5)react组件中观测到数据发生改变(store.subscribe),会从store里面重新取数据(state),更新组件的内容,页面发生变化。
actionTypes 拆分管理,统一管理,方便排错 使用actionCreator统一创建action
- index.js
import {createStore} from 'redux';
import reducer from './reducer';
const store = createStore(
reducer,
// redux-devtools工具调试
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
export default store;
- reducer.js
import {CHANGE_INPUT_TYPE,ADD_LIST_ITEM,DELETE_LIST_ITEM} from './actionTypes';
const defaultState = {
inputValue: '',
list: []
}
export default (state=defaultState, action)=>{
// console.log(state,action);
if(action.type === CHANGE_INPUT_TYPE){
// 深拷贝,reducer不允许直接修改state
const newState = JSON.parse(JSON.stringify(state));
newState.inputValue = action.value;
return newState;
}
if(action.type === ADD_LIST_ITEM){
const newState = JSON.parse(JSON.stringify(state));
newState.list.push(newState.inputValue);
newState.inputValue = '';
return newState;
}
if(action.type === DELETE_LIST_ITEM){
const newState = JSON.parse(JSON.stringify(state));
newState.list.splice(newState.index,1);
return newState;
}
return state;
}
- TodoList .js
import React,{Component} from 'react';
import { Input,Button,List } from 'antd';
import store from './store';
import {getAddItemAction,deleteItemAction,getChangeItemAction } from './store/actionCreator';
import 'antd/dist/antd.css';
class TodoList extends Component {
constructor(props) {
super(props);
this.state = store.getState();
console.log(this.state);
store.subscribe(this.handleStoreChange);
}
render(){
const {inputValue,list} = this.state;
return (<div>
<Input onChange={this.handleInputChange} placeholder={inputValue} style={
{width:'300px',marginLeft:'10px',marginTop:'10px'}} />
<Button onClick={this.handleAddItem} type="primary" style={
{marginLeft:'10px',marginTop:'10px'}} >提交</Button>
<List style={
{marginLeft:'10px',marginTop:'10px',width:'300px'}}
bordered
dataSource={list}
renderItem={(item,index) => (<List.Item onClick={this.deleteItemClick.bind(this,index)}>{item}</List.Item> )}
/>
</div>
);
}
handleInputChange = (e) => {
// console.log(e.target.value);
const action = getChangeItemAction(e.target.value);
store.dispatch(action);
}
handleAddItem = () => {
const action = getAddItemAction();
store.dispatch(action);
}
deleteItemClick(index) {
const action = deleteItemAction(index);
store.dispatch(action);
}
handleStoreChange = () => {
// console.log('handleStoreChange');
this.setState(store.getState());
}
}
export default TodoList;
- actionTypes.js
export const CHANGE_INPUT_TYPE ='change_input_type';
export const ADD_LIST_ITEM = 'add_list_item';
export const DELETE_LIST_ITEM = 'delete_list_item';
- actionCreator.js
import {ADD_LIST_ITEM ,DELETE_LIST_ITEM,CHANGE_INPUT_TYPE } from './actionTypes';
export const getChangeItemAction = (value) => ({
type: CHANGE_INPUT_TYPE,
value
});
export const getAddItemAction = () => ({
type: ADD_LIST_ITEM,
});
export const deleteItemAction = (index) => ({
type: DELETE_LIST_ITEM,
index
});
6、redux知识点
- redux三个基本原则: ①:store必须是唯一的 ②:只有store可以改变自己的内容 ③:reducer 必须是纯函数
- 只有store能改变自己内容说明在reducer里我们不能直接操作state,只能通过定义新变量copy state的值, 然后对新变量进行操作并 return 出新变量,不允许直接改变state。
- 什么是纯函数? 给固定的输入,就一定会有固定的输出,并且不会有任何副作用。 所以对于异步函数(定时器、ajax数据请求等)、动态时间都不适意在reducer里订阅。
- store核心api: crerteStore(): 创建一个store store.dispatch(action): 派发action,传递store store.getState(): 获取store的所有数据 store.subscribe(): 订阅store的变化,接收的回调函数在store改变时候就会自动执行
本文由来源 jackaroo2020,由 javajgs_com 整理编辑,其版权均为 jackaroo2020 所有,文章内容系作者个人观点,不代表 Java架构师必看 对观点赞同或支持。如需转载,请注明文章来源。