认识redux
一提到redux就会想到react,但是redux跟react的关系不像vue和vuex的关系(vuex是专为vue创建的),redux与react并无直接关系,一般使用react-redux把react和redux联系起来,它一般用于数据的公共存储
redux的流程
根据上图分析redux,首先redux有一个仓库(store),在这个store中存放state,和事件池,每当state中有变化就会触发事件池中的所有方法执行(这也是redux的弊端,一个改变无关的也要重新执行),有一个reducer(纯函数)相当于是store的管理员,在这里要根据action中的type去改变state,返回改变后的state把store中的state改变,想要获取state可用方法store.getState(),想要修改state中的方法就要store.dispatch(action对象)这里通过dispatch调用reducer改变相应的值,通过store.subscribe向事件池中添加方法
import {createStore} from 'redux'
function reducer(state={
},action){
switch (action.type){
case "xxx":
break;
case "yyy":
break;
}
return state
}
let store =createStore(reducer)
源码
(function(){
class Store{
constructor(reducer){
this.state=reducer(undefined,{type:"?"+Math.random()})
this.pond=[]
this.reducer=reducer
}
getState(){
//深拷贝一个state为了外面不规范的操作修改同一对象,这样本身的state不会改变,这里只提供使用
return JSON.parse(JSON.stringify(this.state))
}
dispatch(action){
let state=JSON.parse(JSON.stringify(this.state))
this.state=this.reducer(state,action)
this.pond.forEach(item=>{
if(typeof item==="function"){
item()
}
})
}
subscribe(func){
if(typeof func!=="function")return
this.pond.push(func)
}
}
window.createStore=function(reducer){
return new Store(reducer)
}
})()
总结
从redux中导入一个方法传入reducer返回一个store实例,store实例可调用多个方法,最好定义一个Store实例,并在原型上添加getStore(),subscribe(),dispatch(方法)通过这些方法修改每个store中的state,为pond添加方法,获取state值,每个store实例有两个私有属性state和pond,每当state改变pond中的所有方法都会执行一遍,所谓的getState()就是拿到store对象的state对象,最好把他深度拷贝一份,这样可以避免不规范的修改,subscribe就是把传进来方法放到事件池中,而dispatch就是传递一个 action,通过对象的type不同改变修改state,并返回一个新的state赋给store对象的 state,同时把pond中的所有方法执行一遍,state的初始值就是执行reducer不传第一个参数的返回值
redux的缺点与优化
当state中的数据改变时,pond中的方法都会执行,而一班都是各个用到redux中数据的组件在componentDidMount钩子函数中调用 store.subscribe(()=>{this.forceUpdate()}),也就是不管redux中改变的state这个组件使没使用都会重新渲染组件,为了优化这一现象可以把redux中该组件用到的数据把值给当前组件state,在为pond添加方法时把当前组件用到的redux中的数据得到对比与state是否相同如果不同,就要调用setState方法改变state同时渲染页面,这样方法会执行但是页面只有当前用到的值改变时才会重新渲染页面
redux的工程化
reducer的工程化,就是要把reducer拆开,每个文件暴漏一个reducer方法(reducer方法)最后每个小reducer引入一个文件,文件中引入import {combinReducers} from "redux",引入后把每个reducer通过combinReducers({})方法(返回值是reducer)注册到总的reducer,对于reducer中检测type还是dispatch(action)时的type要保持一致,最好把他放到一个变量中,两边使用变量,对于dispatch的action要分多个文件,每个文件返回一个对象,每个对象有对应action的方法便于调用时传入参数返回一个
action,把所有的action文件引到一个文件中导出一个大的action