Redux 知识点 及 使用案例
Posted YuLong~W
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redux 知识点 及 使用案例相关的知识,希望对你有一定的参考价值。
Redux
Redux简介
- redux是一个专门用于做状态管理的JS库(不是react插件库)。
- 它可以用在react,angular, vue等项目中, 但基本与react配合使用。
- 作用:集中式管理react应用中多个组件共享的状态。
使用场景:
- 某个组件的状态,需要让其他组件可以随时拿到(共享)。
- 一个组件需要改变另一个组件的状态(通信)。
- 总体原则:能不用就不用, 如果不用比较吃力才考虑使用。
设计思想:
- Redux 是将整个应用状态存储到一个叫做 store 的地方,里面存在一个状态树 state tree
- 组件可通过 store.dispatch 派发行为 action 给 store,store 不会直接修改 state, 而是通过用户编写的 reducer 来生成新的 state ,并返回给 store
- 其它组件通过订阅 store 中的 state 状态变化来刷新自己的视图
三大原则:
- 整个应用有且仅有一个 store, 其内部的 state tree 存储整个应用的 state
- state 是只读的,修改state,只能通过派发 action,为了描述 action 如何改变 state 的,需要编写 reducer 纯函数
- 单一数据源的设计让 React 组件之间通信更加方便,也有利于状态的统一管理
三个核心概念
1、action
- 动作的对象
- 包含2个属性:
- type:标识属性,值为字符串, 唯一, 必要属性
- data:数据属性, 值类型任意,可选属性
- 例子:{ type: ‘ADD_STUDENT’,data:{name: ‘tom’,age:18} }
2、reducer
- 用于初始化状态、加工状态。
- 加工时,根据旧的state和action, 产生新的state的纯函数。
3、store
-
redux库最核心的管理对象
-
将state、action、reducer联系在一起的对象。它内部维护着:①state ②reducer
-
如何得到此对象
- import {createStore} from ‘redux’
- import reducer from ‘./reducers’
- const store = createStore(reducer)
-
此对象的功能
- getState(): 得到state
- dispatch(action): 分发action,触发reducer调用,产生新的state
- subscribe(listener): 注册监听,当产生了新的state时,自动调用
相关API方法
创建核心对象方法:
createStroe(): Redux 提供createStore这个函数,用来生成 Store。
import {createStroe} from 'react'
function reudcer(){}
let store = createStore(reudcer)
手写实现 createStroe函数功能的代码:
function myCreateStore(reducer){
let state;
const listeners = [];
//返回最新的state
function getState () {
return state;
}
//派发action
function dispatch(action){
state = reducer(state,action);
listeners.forEach(listener=> listener())
}
//订阅,返回取消订阅函数
function subscribe(listener){
listeners.push(listener);
return function (){
const index = listeners.indexOf(listener);
listeners.splice(index,1);
}
}
//获取state默认值
dispatch({type: "不想上学---@@redux/INITg.u.b.z.n.n"});
//返回store,一个对象
return {
getState,
dispatch,
subscribe
}
}
export default myCreateStore;
store的三个核心方法:
①store.getState()
: 可获取最新的 state, 点击按钮,会通过 ②store.dispatch()
派发 action 给 store (注意: action 是个对象,必须存在 type 属性),store 内部会将当前 state,action 传递给 reducer 来生成新的 state 达到更新状态的目的
③store.subscribe()
: 页面不更新的原因在于没有订阅 store 中 state 的变化 。该方法可以实现订阅,该方法接受一函数,当 store 中 state 中状态发生变化,就会执行传入的函数,同时 store.subscribe 方法返回一个函数,用于取消订阅
其他方法:
- bindActionCreators(): 派发 action 的函数与 store.dispatch 进行绑定
- applyMiddleware(): 应用上基于redux的中间件(插件库)
- combineReducers(): 合并多个reducer函数
案例——用React+redux实现数字求和
效果展示:
文件目录结构:
安装redux库:npm install redux
/ yarn add redux
异步所需要的库:npm install redux-thunk
/yarn add redux-thunk
index.html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
App.js文件:
import React,{Component} from "react";
import Count from "./components/Count";
export default class App extends Component{
render(){
return(
<div>
<Count/>
</div>
)
}
}
index.js文件:
import React from "react";
import App from "./App";
import ReactDOM from 'react-dom';
import store from "./redux/store";
ReactDOM.render(<App/>,document.getElementById('root'))
//监测redux中状态的改变。如果redux状态发生改变,则重新渲染App组件
store.subscribe(()=>{
ReactDOM.render(<App/>,document.getElementById('root'))
})
redux目录下文件:(4个文件)
1、constant.js文件:
/*
该模块是用于定义action对象中type类型的常量值,目的只有一个:便于管理的同时防止程序员单词写错
*/
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
2、count_action.js文件:
/*
该文件专门为Count组件生成action对象
*/
import {INCREMENT,DECREMENT} from './constant'
export const createIncrementAction=data=>({type:INCREMENT,data})
export const createDecrementAction=data=>({type:DECREMENT,data})
//异步加
export const createIncrementAsyncAction=(data,time)=>{
return(dispath)=>{
setTimeout(()=>{
dispath(createIncrementAction(data))
},time)
}
}
3、count_reducer.js文件:
/*
1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数
2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
*/
//初始化状态
const initState=0;
export default function countReducer(preState=initState,action){
//从action对象中获取:type、data
const {type,data}=action
//根据type决定如何加工数据
switch (type){
case 'increment':
return preState+data
case 'decrement':
return preState-data
default:
return preState
}
}
4、store.js文件:
/*
该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/
// 引入creatStore 专门用于创建redux最核心的store对象
import {createStore} from "redux";
// 引入applyMiddleware 作为中间件来应用thunk
import {applyMiddleware} from "redux";
//引入为Count组件服务的reducer
import countReducer from'./count_reducer'
//引入redeux-thunk,用于支持异步action
import thunk from "redux-thunk";
//暴露store
// export default createStore(countReducer);
//如果要用异步action,必须采用
export default createStore(countReducer,applyMiddleware(thunk));
components-Count目录下的index.jsx文件:
import React, { Component } from 'react'
//引入store 用于获取redux中保存状态
import store from "../../redux/store";
//引入actionCreator,专门用于创建action对象
import {
createIncrementAction,
createDecrementAction,
createIncrementAsyncAction
} from '../../redux/count_action'
export default class Count extends Component{
//加法
increment = ()=>{
const {value} = this.selectNumber
store.dispatch(createIncrementAction(value*1))
}
//减法
decrement = ()=>{
const {value} = this.selectNumber
store.dispatch(createDecrementAction(value*1))
}
//奇数再加
incrementIfOdd = ()=>{
const {value} = this.selectNumber
const count = store.getState()
if(count % 2 !== 0){
store.dispatch(createIncrementAction(value*1))
}
}
//异步加
incrementAsync = ()=>{
const {value} = this.selectNumber
// setTimeout(()=>{
// store.dispatch(createIncrementAction(value*1))
// },500)
//将定时器放入异步action中 在这里只需调用
store.dispatch(createIncrementAsyncAction(value*1,500))
}
render() {
return (
<div>
<h1>当前求和为:{store.getState()}</h1>
<select ref={c => this.selectNumber = c}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={this.incrementAsync}>异步加</button>
</div>
)
}
}
案例知识点总结:
1、src目录下建立以下结构:
-redux
-store.js
-count_reducer.js
-count_action.js
-constant.js
-
1)store.js:
- 引入redux中的createStore函数,创建一个store
- createStore调用时要传入一个为其服务的reducer
- 记得 暴露store对象
-
2)count_reducer.js:
- reducer的本质是一个函数,接收:preState,action,返回:加工后的状态
- reducer有两个作用:初始化状态,加工状态
- reducer被第一次调用时,是store自动触发的,
- 传递的preState是 undefined
- 传递的action是:{type:’@@REDUX/INIT_a.2.b.4}
-
3)count_action.js:
- 专门用于为组件创建action对象
-
4)constant.js:
- 用于定义action对象中type类型的常量值。方便后期管理和避免出错
2、注意:
- 在index.js中需要监测store中状态的改变,一旦发生改变重新渲染
<App/>
- redux只负责管理状态,至于状态的改变驱动着页面的展示,需要靠自己写
3、异步action:
- 明确:延迟的动作不想交给组件自身,想交给action
- 何时需要异步action:想要对状态进行操作,但是具体的数据靠异步任务返回。
- 具体编码:
yarn add redux-thunk
,并配置在store中- 创建action的函数不再返回一般对象,而是一个函数,该函数中写异步任务。
- 异步任务有结果后,分发一个同步的action去真正操作数据。
- 备注:异步action不是必须要写的,完全可以自己等待异步任务的结果了再去分发同步action。
以上是关于Redux 知识点 及 使用案例的主要内容,如果未能解决你的问题,请参考以下文章