滴水能把石穿透,萬事功到天然成—zZ先森vue
衆所周知,無論是react-redux仍是vuex,都是參考於redux的公共狀態管理機制。那麼搞清楚redux的運行原理,也就搞明白了倆大視圖框架的公共狀態的一個管理模式。接下來,讓咱們探究一下它究竟是如何作到的。react
看到首圖很懵吧?首先,以個人理解,先歸納一下上圖所表達的Redux運行原理。vuex
不難理解,管理公共狀態,首先得給他找個地方存儲,我把它稱爲倉庫。倉庫裏有倆個地方分別存放了狀態和修改狀態的事件,稱爲狀態池和事件池,倉庫並提供了操做狀態和事件的方法。redux
store.getState()
獲取倉庫中的狀態各個組件經過此方法獲取用到的公共狀態,做爲渲染視圖的數據。bash
reducer
充當了倉庫的管理角色,每一個組件操作狀態都得經過reducer。reducer
做爲英文單詞是減速器、縮減者的意思。在這裏的意思是操做狀態,管理行爲,讓組件更加有秩序地、有規則地從倉庫裏獲取狀態信息。reducer是一個函數,有倆個參數分別是:【state】【action】,在接收組件dispatch傳遞進來的行爲對象,傳遞給action,進而作相應的處理。action是一個對象,並保證type
屬性的存在,用來識別該行爲。state攜帶的就是倉庫的初始數據,倉庫只不過是給reducer提供一個存儲數據的地方。經過對action的操做返回最新修改後的狀態信息,同時把倉庫中的狀態修改了。框架
store.subscribe()
往倉庫的事件池中訂閱方法各個組件爲了後期能獲取到最新的狀態,提早向組件中訂閱修改本身狀態的方法,一旦倉庫中的狀態改變,組件會從新渲染。async
store.subscribe()方法執行的返回值是從事件池中移除方法的函數:unsubscribe()ide
store.dispatch()
派發一個任務告知reducer修改倉庫中的狀態。派發的就是一個帶有type
的對象,經過type
來標識修改哪一個狀態。最後各個組件都能有效的實時更新,實現了公共狀態的管理以及各個組件之間的通訊。函數
dispatch
subscribe
getState
replaceRedecer
[$$observable]:observable
用戶使用getState,克隆一份新的狀態,防止直接修改性能
對於添加事件池中,作去重處理
防止在reducer中直接修改狀態
克隆一份新的狀態,並返回 咱們知道確實是經過派發任務通知reducer去修改狀態,可是咱們在操做狀態的時候爲了能一次性更新,且在修改的時候不破壞原有的狀態,防止形成狀態的混亂,有必要克隆一份新的狀態。在咱們使用reducer的時候,也是新克隆一份。
JSON.parse(JSON.stringify(xxx))
對於狀態沒有更新,咱們不通知事件池中的方法執行,從而提升性能。用深比較。
//優化一 深克隆
export cloneDeep(obj){
if(obj===null) return null;
if(typeof obj!=="function") return obj;
if(obj instanceof RegExp) return new RegExp(obj);
if(obj instanceof Date) return enw Date(obj);
let clone = new obj.constructor;
Object.keys(obj).forEach(item=>{
clone[item] = cloneDeep(obj[item])
})
return clone
}
export function createStore(reducer){
if(typeof reducer!=="function"){
throw new TypeError("Expected the reducer to be a function ")
}
//state存放狀態 listener
存放事件池
let state,
isdispatch =false;
listeners = [];
//獲取狀態
getState(){
//優化一:把返回的信息進行深克隆,這樣讀取到的狀態信息,不能直接基於對象.xx修改了
return cloneDeep(state)
}
//向事件池中追加方法
function subscribe(func){
if(typeof!=="function"){
throw new Error('Expectted the listener to be a function ')
}
//優化二
if(!listeners.includes(func)){
listeners = listeners.push(func);
}
return function unsubscribe(){
listeners.filter(item=>{
item!==function
})
}
}
//派發任務
function dispatch(action){
if(func===null||typeof action!=="object"){
throw new Error(
'Action must be plain objects.'+'Use custom middleware for async actions'
)
}
if(typeof action === 'undefined'){
throw new Error(
'Action may not have an undefined 'type' property'+'have you misspelled a constant?'
)
}
//優化三 防止在reducer中修改狀態,不用用戶本身手動克隆state,這裏能夠深克隆一下
let preState = state;
state = reducer(state,action);
//優化四 深比較 沒有修改則不通知listeners中的方法執行
if(!compareDeep(preState,state){
listeners.forEach(item=>{
item();
})
}
}
//默認建立store 就執行一次dispatch 目的是給狀態賦初始值
dispatch({
//不能和後期用戶的action.type衝突
type:Symbol('INIT')
})
return {
setState,
subscribe,
dispatch
}
}
//優化四 深比較
export compareDeep(val1,val2){
let type1 = typeof val1,
type2 = typeof val2;
if(type1===null&& type2===null){
return true
}
if(type1==="function"&&type2==="function"){
return val1.toString === val2.toString
}
if(type1==="object"&&type2==="object"){
let ct1 = val1.costructor,
ct2 = val2.constructor;
if((ct1===RegExp&&ct1===RegExp)||(ct2===Date&&ct2===Date)){
return val1.toString() === val2.toString()
}
let key1 = Object.keys(val1),
key2 = Object.keys(val2);
if(key1.length===key2.length){
key1.forEach(item=>{
let value1=val1[item],
value2=val2[item];
let res = compareDeep(value1,value2);
if(!res) return res
})
}
return false;
}
//基本數據類型 直接基於三個等於號比較便可
return val1===val2
}
複製代碼
React-redux是React基於Redux封裝的狀態管理庫,基於Redux,它作了如下三個大事情:
思惟導圖:
React-redux部分源碼
import React from 'redux';
import PropTypes from 'prop-types';
const ThemeContext = React. creatContext();
export class Provider extends React.Component{
static propTypes = {
store:PropTypes.object.isRequired
};
render(){
<ThemeContent value={
{
store:this.props.store
}
}>
//真實要渲染的組件拿過來渲染
{this.props.children}
</ThemeContent>
}
}
export function connect(mapStateToProps,mapDispatchToProps){
//初始化參數
if(typeof mapStateToProps!=="function"){
mapStateToProps = state=>{
return{}
}
}
if(typeof mapDispatchToProps!=="function"){
if(mapDispatchToProps!==null&& typeof mapDispatchToProps==='object'){
let action = mapDispatchToProps;
mapDispatchToProps = dispatch=>{
let obj = {};
Object.keys(action).forEach(item=>{
obj[item] = (...args)=>{
dispatch(action[item](...args))
}
})
return obj;
}
}
mapDispatchToProps = dispatch=>{
return{}
}
}
return function connectHOC(component){
return class proxy texends React.Component{
static contextType = ThemeContext;
render(){
return <component/>;
}
queryPros=()=>{
let { store } = this.conext,
state = store.getState(),
dispatch = store.dispatch;
return {
...mapStateToProps(state);
...mapDispatchToProps(dispatch)
}
}
componentDidMount(){
this.context.store.subscribe(()=>{
this.forceUpdate();
})
}
}
}
}
複製代碼