安装: npm install --save redux react-redux redux-thunk 参考地址:
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)
2019-01-22
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:"自定义" })
Document
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 dispatch12 }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.color45 }46 function renderContent(){47 let content = document.querySelector('.content');48 content.innerHTML = store.getState().contentState.text;49 content.style.color = store.getState().contentState.color50 }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();//每次派发完都需要render60 },3000)