安装: npm install --save redux react-redux redux-thunk
参考地址:https://www.jianshu.com/p/06f5285e2620
Redux:
reduce + flux ( 是一个可预测的状态管理容器。)
Redux 三大原则:
1.整个应用的 state 被存储在一棵 object tree 中,并且这个 object tree
只存在于唯一一个 store 中
2.state 是只读的,唯一改变 state 的方法基于是触发 action,action 是
一个用于描述已发生事件的普通对象使用纯函数来执行修改,为了描述
action 如何改变 state tree,你需要编写 reducers
3.单一数据源的设计让 react 的组件之间的通信更加方便,同时也便于状态统一管理
三大核心:
reducer 必须传入一个纯函数
action 要处理哪个逻辑
store 联系和管理
state 就为初始化数据
action 要处理哪个逻辑
reducer
function reducer(state={num:0},action){
switch(action.type){
case "ADD":
let state = Object.assgin({},state);
state.num ++;
return state; //state 为新的地址
}
}
store:就是保存数据的地方,你可以把它看成一个仓库(容器)。整个应用只有一个 store
const store = createStore(reducer);
reducer:(管理员 机制)必须是个纯函数,所有的状态更改都要经过reducer,基于不同的行为标识,修改store中不同的状态
纯函数 -> 对于任何相同的输入有着相同的输出结果
简单来说:
每次发起了 action,action 处理之后的结果为新地址的 state
//STATE:
//ACTION:
function reducer(state,action){
switch(action.type){
case "ADD":
let state = Object.assgin({ },state);
state.num ++;
return state; //state为新的地址(返回的值会把原始STORE中的状态信息替换掉)
}
}
store.dispatch({type:'ADD'}) 发起一个action(action:传进来的行为)
store.getState() 读取状态数据
store.subscribe(()=>{}) 向事件池中追加方法,当STORE中的状态改变,强制更新当前组件(能监听(订阅)状态的变化(只要状态发生了变化,就执行subscribe的方法))
react-redux 基于redux开发的更适用于react中的状态管理插件。(2019-2-22,周老师)
Provider 必须在顶层
import {Provider} from 'react-redux';
有 router 有 redux 就是
<Provider>
<Router>
<App/>
</Router>
</Provider>
只有 redux
<Provider>
<App/>
</Provider>
使用 react-redux + redux 的内功心法。
1.引包 react-redux 中的 Provider,redux 中的 createStore
import { Provider } from " react-redux " import { cteateStore } from " redux "
2.创建 store
const store = createStore(reducer);
3.
<Provider store={store}>
<App/>
</Provider>
4.哪个组件需要 *使用数据*
就在哪个组件中引入 react-redux 中的 connect
import {connect} from 'react-redux' import { bindActionCreators} from 'redux'
在导出的地方 把组件用 connect 包一下
connect((state)=>state)(组件的名字)
比如:
export default connect((state)=>state,(dispatch)=>{
return bindActionCreators(actioncreators,dispatch);
})(组件的名名字);
state 就是 reducer 下的 state 状态
那么做之后,就可以通过 this.props.xx 去获取状态值
this.props.dispatch 去发起 action
注意点:
***如果使用了 connect 路由跳转会失效,此时要使用withRouter解决
比如:
export default withRouter(connect(state=>state,(dispatch)=>bindActionCreators(actioncreators,dispatch))(App));
***数据变化了,视图却没有更新,应该注意state是否需要深克隆 可以用JSON.parse(JSON.stringify( arr ))
// export defore connect((state)=>{
/*
!!! 此处一定要返回一个对象
可以选择这个组件能用的数据。默认全部数据都返回
*/
})(App)
reducer中state可以是简单类型也可以是复合类型
如果是简单类型是可以直接更改state的
如果是复合类型的,每一次修改必须赋值一个新的地址,方便管理
state = {a:5}
state = {a:6}
[{a:5},{a:6}]
redux:
createStore(reducer,initialstate,middleware)
initialstate:初始值
middleeware:中间件的接口
也可以这么写:
createStore( reducer,middleware)
用的比较多的 thunk (为了异步操作,用 applymiddleware(thunk) ),thunk 是中间件。??????????????????????
combineReducers({})
可以放入多个 reducer
bindActionCreators(actioncreats,dispatch)
返回一个对象,可以把actions直接挂到this.props下
actioncreators
发起action的小函数
const ADD = 'ADD'; 为了让action是唯一,所以用变量。
function add(){
return {
type:ADD
}
}
react-redux
Provider 挂在顶层,并且挂一个属性叫store={store}
connect 哪个组件需要状态管理器中的数据,就用connect包裹
返回新的组件
let mapStateProp = (state,ownProps)=>{
state状态管理器中的所有数据,
也可以返回一个当前组件需要的数据
return state; //必须返回对象
}
let mapDispatchProp = (dispatch,ownProps) => {
return bindActionCreators(actionCreators,dispatch)
}
ownProps:只要接收到的新的父级传进来的数据,就会在运行一次此函数
connect(mapStateProp,mapDispatchProp)(App)
英文储备:
redux “统一”的状态管理,不能直接更改状态
state 状态
type 类型
createStore 创建文件
getState 获取状态
initState 初始状态
reducer 管理员,负责如何更改状态
dispatch 派发 (参数是 action 动作,规定action是一个对象,这个对象必须有一个type属性 { type:"自定义" })
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div class="title"></div> <div class="content"></div> <script src="./试试.js"></script> </body> </html>
1 // redux “统一”的状态管理,不能直接更改状态 2 function createStore(reducer) { //将状态放到一个盒子里,别人就改不了了。 3 let state;//状态 4 function dispatch (action){ //派发 参数是action 动作,规定action是一个对象,这个对象必须有个type属性{type:'自定义'} 5 state = reducer(state,action);//调用写好的方法,这个方法会返回一个新的状态,覆盖掉老状态 6 }; 7 dispatch({}); 8 let getState = () =>JSON.parse(JSON.stringify(state)) //获取状态的方法 9 return { 10 getState, 11 dispatch 12 } 13 } 14 15 16 let initState = { //初始状态 17 titleState:{color:'red',text:'标题'}, 18 contentState:{color:'green',text:'内容'}, 19 } 20 21 22 let store = createStore(reducer);//创建容器时需要传递一个管理员 23 24 25 function reducer(state=initState,action){ //管理员,负责如何更改状态 26 switch (action.type){ //更改状态 要用一个新的状态覆盖掉 27 case 'CHANGE_TITLE_TEXT': 28 return{...state,titleState:{...state.titleState,text:action.text}}; 29 case 'CHANGE_CONTENT_COLOR': 30 return{...state,contentState:{...state.contentState,color:action.color}}; 31 } 32 return state; 33 } 34 35 36 //宏 定义一个常量 37 const CHANGE_TITLE_TEXT = 'change_title_text'; 38 const CHANGE_CONTENT_COLOR = 'change_content_color'; 39 40 41 function renderTitile(){ 42 let title = document.querySelector('.title'); 43 title.innerHTML = store.getState().titleState.text; 44 title.style.color = store.getState().titleState.color 45 } 46 function renderContent(){ 47 let content = document.querySelector('.content'); 48 content.innerHTML = store.getState().contentState.text; 49 content.style.color = store.getState().contentState.color 50 } 51 function renderApp(){ 52 renderTitile() 53 renderContent() 54 } 55 renderApp() 56 setTimeout(()=>{ 57 store.dispatch({type:'CHANGE_TITLE_TEXT',text:'长标题'}) //除了type的属性,其它的都叫payload 载荷 58 store.dispatch({type:'CHANGE_CONTENT_COLOR',color:'blue'}) 59 renderApp();//每次派发完都需要render 60 },3000)