redux
javascript提供的一个可预测性的状态容器(我们给一个固定的输入 那麽必定可以得到结果)
集中的的管理react当中多个组件的状态
redux是一个专门的状态管理库 (是一个插件 在vue也可以使用 但是在react比较多)
cnpm istall redux --save
store 状态仓库
reducer 处理业务逻辑
需求场景
某个组件的状态需要共享的时候
一个组件需要改变另一个组件状态的时候
组件的状态需要在任何地方可以拿到
三大原则
1.单一数据源 整个react中的状态 都会被统一的管理到store里面
2.state是只读的 不能够直接改变state 二是通过触发redux中的特定方法修改state
3.使用纯函数来执行修改操作:action来改变redux的state
初始化阶段通过store.getState() 获取
redux 可以理解为:界面上触发了需要改变数据的事件会在callback里面创建action 并且用dispatch提交action 这个action会被提交到store里的reducer(可以是一个模块,也可能与创建store集成在一起,也可能是用hooks创建的reducer) 接收到action提交后 会首先比较type类型 再利用action里的其他属性 在对应代码块里进行逻辑操作 实现状态的变化
1.辅助工具 :store一被提交的action修改 可以使用store.subscribe(“回调”)更新到新的状态 实现’刷新‘
const [val,setVal] = useState(store.getState())
const getNewState=()=>{
setVal(()=>{return store.getState()}) //setVal 的更新可能是异步的 所以要传一个callback
}
store.subscribe(getNewState)
2.如何在全局调用store的具体数据
react-redux
Provider 提供器 将store的状态给到 组件 【一般是在入口函数 或者父组件使用 包裹住需要拿到状态的组件】
connect 在上面被包裹的组件 导出的时候再来一次包裹 connect(mapStateToprops,mapDispatchToprops)(App) connect的两个方法会将状态 和修改状态的方法 dispatch 通过props传给 包裹住的组件【这两个方法的使用场景是已经有store的时候 将state给到需要组件 】
入口函数:引入Provider 包裹住引来的跟组件
跟组件:再导出时 在外套上connect(mapStateToprops,mapDispatchToprops)(App) 两个形参介绍如下
const mapStateToprops=(state)=>{
return state
}
const mapDispatchToprops=(dispatch)=>{
return(
add(e){
const action ={
type="ADD_ITEM",
value=e.target.val
}
dispatch(action)
},
)
}
3.要调用多个接口 且需要存在store中时 按需拿到 少调接口 所以要分别对应不同的reducer, 合并reducer
const reducer = combineReducer({
user:data1,
product:data2
})
const store = createStore(
reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
4.useContext 上下文 个人理解:
与eventBus相似 在总线中
A.vue 与 B.vue 需要引入总线传参import EventBus from “event Bus.js ”
A.vue
method:{
toFriend(e){
EventBus.$emit("coming",e.target)
}
}
B.vue
created(){
EventBus.$on("coming",target=>{
console.log(target)
})
}
vue路由懒加载
1.正常情况下
import Hello from './components/Hello'
2.使用ES的懒加载
const Hello = ()=>import('./components/Hello')
在路由规则里 component:()=>import ('./components/Hello')
3.require
component : resolve =>{require('[./components/Hello]',resolve)}
useContext的模拟使用 用上面的 文件名模拟
eventBus.jsx:
export const Acontext = createContext() //创建一个上下文 并暴露
export const Bcontext = createContext()
const [count,setCount] = useState('0')
const [name,setName] = useState('kenny')
return (
<div>
<Acontext.Provider value={count}>
<A />
</Acontext.Provider>
<Bcontext.Provider value={name}>
<b />
</Bcontext.Provider>
</div>
)
A.jsx:
const count = useContext(Acontext)
{count}
B.jsx:
const name= useContext(Bcontext)
{name}
usereducer
接受两个参数,一个是reducer,一个是状态的默认值, reducer接受两个参数 一是state 一是action(这里的state就是状态的默认值)
然后返回一个状态count和dispatch dispatch可以发布事件 更新state
import React,{useReducer} from "react"
function Text(){
const [count,dispatch] = useReducer((state,action)=>{
switch(action.type){
case "add"
return state + +action.val
case "del"
return state - action.val
}
},10)
return(
<div>
<p>{count}</p>
<button onClick={()=>{return dispatch({type:"add",val:2})}}>增2</button>
<button onClick={()=>{return dispatch({type:"del",val:3})}}>减3</button>
</div>
)
}
createContext 创建上下文 useReducer与useContext 相结合 可以实现 redux的作用
这里需要专门建立模块的利用useContext的上下文暴露 (contextName.Provider)将useReducer的状态和diapatch暴露出去
不过需要注意 这里导出的该模块 是要将可能用到state状态的某些模块包裹起来 再在相应的模块里面用对象解构引用上下文
redux-thunk 可以dispatch一个函数 中间件
redux-saga 用于管理redux应用异步操作的中间件 (又称异步action)
saga 通过创建sagas 将所有的异步操作逻辑收录在一起 可以代替thunk中间件
sagas通过Generator来创建 可以用同步的方式写异步代码
thunk是在action被创建时调用 saga则是在应用启动时调用 监听发起的action 基于这个action来做什么
useSlector
在函数组件中结合reducer使用方便快捷(推荐使用)与useDispatch搭配使用
const {keyword} = useSelector(state => state.search);