隨着全局狀態管理庫如vuex,mobx,redux的盛行,人們愈來愈習慣把狀態一股腦丟在狀態管理庫裏面,卻忘了去劃分狀態的級別。這種濫用全局狀態管理庫的現象一直廣泛存在。vue
就是沒有認識到狀態管理庫的根本做用,或者說咱們何時才須要狀態管理庫?react
拿 react 來講,react 是有組內狀態的,狀態能夠經過 props 傳遞。可是,但當 app 比較龐大的時候,兄弟組件,遠親組件這些的交流就變得困難起來, 它們必須依賴相同的父組件來完成信息的傳遞。這時,就是咱們使用狀態管理庫的時候。vuex
可是,不少人把全部狀態都往 redux 裏面丟,雖然這方便了開發,但缺點卻很明顯:redux
劃分好狀態的等級,儘可能把狀態放在組件內。當遇到須要共享組內狀態的時候,提高狀態到父級或者全局狀態管理庫。api
你能夠把view、model、loadData邏輯都塞進這個組件,這樣它便有了獨立功能。它把複雜度隱藏在內部,而後向外界暴露一些api來提供本身的能力。app
例如一個列表組件:性能
// 方案一
// ListDemo.jsx
import React,{useEffect} from 'react';
import {getData} from 'services/api';
export default function ListDemo({requestId}){
// model
const [data,setData] = useState([]);
const [visible,setVisible] = useState(false);
useEffect(()=>{
// services 層
getData().then(data=>{
setData(data)
});
/**
* 當requestId變化時,列表會從新請求
* 這裏的requestId是組件向外界暴露的一個api
**/
},[requestId])
useEffect(()=>{
if(visible===true){
// clearState
setVisible(false);
}
},[requestId])
return (
// view
<div>
{
data.map(item=><li>{item}</li>
}
{
visible && (
<div>
this is a modal
</div>
)
}
</div>
)
)
}
// app.jsx
<ListDemo />
複製代碼
這種組件設計的特色是,組件能夠重置自身狀態的時機是由自身控制的。若是你以爲這樣麻煩,你能夠把重置自身狀態的時機交給外部,經過key來 「銷燬組件」=>「從新渲染組件」。上面的代碼能夠簡化成:this
// 方案二
// ListDemo.jsx
import React,{useEffect} from 'react';
import {getData} from 'services/api';
export default function ListDemo({requestId}){
// model
const [data,setData] = useState([]);
const [visible,setVisible] = useState(false);
useEffect(()=>{
// services 層
getData().then(data=>{
setData(data)
});
},[])
return (
// view
<div>
{
data.map(item=><li>{item}</li>
}
{
visible && (
<div>
this is a modal
</div>
)
}
</div>
)
)
}
// app.jsx
/*
*當requestId變化時,ListDemo會從新渲染
*/
<ListDemo key={requestId} />
複製代碼
方案二的代碼比較整潔,且出錯率比方案一低,可是方案二存在從新渲染組件的一個環節,性能開支會比方案一多一點點(大部分狀況你均可以忽略不計)。不少狀況下,我都會採用方案二。spa