1,什么是 redux
Redux 是一个用来治理治理数据状态和 UI 状态的 JavaScript 利用工具。随着 JavaScript 单页利用(SPA)开发日趋简单,JavaScript 须要治理比任何时候都要多的 state(状态),Redux 就是升高治理难度的。(Redux 反对 React,Angular、jQuery 甚至纯 JavaScript)
react-redux 工作流程
装置 redux
npm install –save redux
简略应用
在 src 下新建 store 文件夹,创立仓库管理文件 index.js
import {createStore, applyMiddleware, compose} from 'redux' // 引入 createStore 办法
import reducer from "./reducer"
const store = createStore(reducer) // 创立数据存储仓库
export default store // 裸露进来
同时创立 reducer.js 文件
// 定义初始 state
const defaultState = {
inputValue: '请输出待办事项',
list: [
'早上 4 点起床,锻炼身体',
'中午上班游泳一小时'
]
}
export default (state = defaultState, action) => {return state}
组件中应用 state 的值
import React, {Component} from 'react';
// 组件中引入 store
import store from './store'
class TodoList extends Component {constructor(props) {super(props)
#获取 store 中 state 的值
this.state = store.getState();
this.clickBtn = this.clickBtn.bind(this)
}
render() {
return (
<div>
<Input placeholder={this.state.inputValue} style={{width: '250px', marginRight: '10px'}} value={this.state.inputValue} />
<Button type="primary" onClick={clickBtn}> 减少 </Button>
</div>
<div style={{margin: '10px', width: '300px'}}>
<List bordered
dataSource={this.state.list}
renderItem={(item, index) => (<List.Item onClick={() => {deleteItem(index)
}}>{item}</List.Item>)}></List>
</div>
);
}
deleteItem(index) {console.log(index)
}
}
export default TodoList;
二,装置 redux 谷歌调试工具
翻墙下载 redux_dev_tool,
在 store/index 文件下增加
import {createStore, applyMiddleware, compose} from 'redux' // 引入 createStore 办法
import reducer from "./reducer"
//const composeEnhancers =
//const enhancers = composeEnhancers(applyMiddleware(thunk))
const store = createStore(
reducer,
window.__REDUX_DEVTOOLS_EXTENSION_ && window.__REDUX_DEVTOOLS_EXTENSION_()) // 创立数据存储仓库, 存在调试工具,开启工具
export default store
三,操作 store 扭转
import React, {Component} from 'react';
// 组件中引入 store
import store from './store'
class TodoList extends Component {constructor(props) {super(props)
#获取 store 中 state 的值
this.state = store.getState();
this.clickBtn = this.clickBtn.bind(this)
this.changeInputValue = this.changeInputValue.bind(this)
#增加订阅 #新版本不必增加订阅 然而 input value 变动须要应用订阅
store.subscribe(this.storeChange)
this.storeChange = this.storeChange.bind(this)
}
render() {
return (
<div>
<Input placeholder={this.state.inputValue} style={{width: '250px', marginRight: '10px'}} onChange={()=>{this.changeInputValue} value={this.state.inputValue} />
<Button type="primary" onClick={this.clickBtn}> 减少 </Button>
</div>
<div style={{margin: '10px', width: '300px'}}>
<List bordered
dataSource={this.state.list}
renderItem={(item, index) => (<List.Item onClick={() => {deleteItem(index)}}>{item}</List.Item>
)}></List>
</div>
);
}
changeInputValue(e){
// 申明 action 对象
const action ={
type:'changeInput',
value:e.target.value
}
// 调用 dispatch
store.dispatch(action)
}
// 订阅更新
storeChange() {this.setState(store.getState())
}
// 增加按钮事件
clickBtn(){
const action ={type:'addItem',}
store.dispatch(action)
}
// 点击删除事件
deleteItem(index) {
const action = {
type:'deleteItem',
index
}
store.dispatch(action)
}
}
export default TodoList;
在 reducer.js 中执行对应 type 类型的操作
// 定义初始 state
const defaultState = {
inputValue: '请输出待办事项',
list: [
'早上 4 点起床,锻炼身体',
'中午上班游泳一小时'
]
}
export default (state = defaultState, action) => {
#reducer 里只能承受 state 不能扭转 state
if(action.type == 'changeInput'){let newState = JSON.pares(JSON.stringify(state)) // 深拷贝 state
newState.inputValue = action.value
return newState
}
// 增加事件
if(action.type == 'addItem'){let newState = JSON.pares(JSON.stringify(state)) // 深拷贝 state
newState.list.push(newState.inputValue)
newState.inputValue = '' // 减少实现,设置为空
return newState
}
// 删除事件
if(action.type == 'deleteItem'){let newState = JSON.pares(JSON.stringify(state)) // 深拷贝 state
newState.list.splice(action.index,1)
return newState
}
return state
}
三,写 redux 的小技巧
- 独立 type 文件
在 store 中新建文件 actionType.js
// 定义常量
export const CHANGE_INPUT = 'changeInput'
export const ADD_ITEM = 'addItem'
export const DELETE_ITEM = 'deleteItem'
export const GET_LIST = 'getList'
在组件中引入 actionType 文件
import React, {Component} from 'react';
// 组件中引入 store
import store from './store'
import {CHANGE_INPUT, ADD_ITEM, DELETE_ITEM, GET_LIST} from './store/actionType'
class TodoList extends Component {constructor(props) {super(props)
#获取 store 中 state 的值
this.state = store.getState();
this.clickBtn = this.clickBtn.bind(this)
this.changeInputValue = this.changeInputValue.bind(this)
#增加订阅 #新版本不必增加订阅 然而 input value 变动须要应用订阅
store.subscribe(this.storeChange)
this.storeChange = this.storeChange.bind(this)
}
render() {
return (
<div>
<Input placeholder={this.state.inputValue} style={{width: '250px', marginRight: '10px'}} onChange={()=>{this.changeInputValue} value={this.state.inputValue} />
<Button type="primary" onClick={this.clickBtn}> 减少 </Button>
</div>
<div style={{margin: '10px', width: '300px'}}>
<List bordered
dataSource={this.state.list}
renderItem={(item, index) => (<List.Item onClick={() => {deleteItem(index)}}>{item}</List.Item>
)}></List>
</div>
);
}
changeInputValue(e){
// 申明 action 对象
#应用引入的常量替换
const action ={
type:CHANGE_INPUT,
value:e.target.value
}
// 调用 dispatch
store.dispatch(action)
}
// 订阅更新
storeChange() {this.setState(store.getState())
}
// 增加按钮事件
clickBtn(){
const action ={type:ADD_ITEM,}
store.dispatch(action)
}
// 点击删除事件
deleteItem(index) {
const action = {
type:DELETE_ITEM,
index
}
store.dispatch(action)
}
}
export default TodoList;
在 reducer.js 中也进行引入
import {CHANGE_INPUT, ADD_ITEM, DELETE_ITEM} from './actionType'
// 定义初始 state
const defaultState = {
inputValue: '请输出待办事项',
list: [
'早上 4 点起床,锻炼身体',
'中午上班游泳一小时'
]
}
export default (state = defaultState, action) => {
#reducer 里只能承受 state 不能扭转 state
if(action.type == CHANGE_INPUT){let newState = JSON.pares(JSON.stringify(state)) // 深拷贝 state
newState.inputValue = action.value
return newState
}
// 增加事件
if(action.type == ADD_ITEM){let newState = JSON.pares(JSON.stringify(state)) // 深拷贝 state
newState.list.push(newState.inputValue)
newState.inputValue = '' // 减少实现,设置为空
return newState
}
// 删除事件
if(action.type == DELETE_ITEM){let newState = JSON.pares(JSON.stringify(state)) // 深拷贝 state
newState.list.splice(action.index,1)
return newState
}
return state
}
- 集中整顿 action 派发
在 store 中新建 actionCreator.js 文件
import {CHANGE_INPUT, ADD_ITEM, DELETE_ITEM} from './actionType'
export const changeInputAction = (value) =>({
type:CHANGE_INPUT,
value
})
export const addItemAction = () =>({type:ADD_ITEM,})
export const deleteItemAction = (index) =>({
type:DELETE_ITEM,
index
})
在组件中引入 actionCreator.js
import React, {Component} from 'react';
// 组件中引入 store
import store from './store'
// 引入 actionCreator.js
import {changeInputAction,addItemAction,deleteItemAction} from './store/actionCreator'
class TodoList extends Component {constructor(props) {super(props)
#获取 store 中 state 的值
this.state = store.getState();
this.clickBtn = this.clickBtn.bind(this)
this.changeInputValue = this.changeInputValue.bind(this)
#增加订阅 #新版本不必增加订阅 然而 input value 变动须要应用订阅
store.subscribe(this.storeChange)
this.storeChange = this.storeChange.bind(this)
}
render() {
return (
<div>
<Input placeholder={this.state.inputValue} style={{width: '250px', marginRight: '10px'}} onChange={()=>{this.changeInputValue} value={this.state.inputValue} />
<Button type="primary" onClick={this.clickBtn}> 减少 </Button>
</div>
<div style={{margin: '10px', width: '300px'}}>
<List bordered
dataSource={this.state.list}
renderItem={(item, index) => (<List.Item onClick={() => {deleteItem(index)}}>{item}</List.Item>
)}></List>
</div>
);
}
changeInputValue(e){const action = changeInputAction(e.target.value)
// 调用 dispatch
store.dispatch(action)
}
// 订阅更新
storeChange() {this.setState(store.getState())
}
// 增加按钮事件
clickBtn(){const action =addItemAction()
store.dispatch(action)
}
// 点击删除事件
deleteItem(index) {const action = deleteItemAction(index)
store.dispatch(action)
}
}
export default TodoList;