[Concent速成] (1) 定義和共享模塊狀態

image

開源不易,感謝你的支持,❤ star concent^_^vue

序言

[Concent速成]是一個幫助新手極速入門concent的系列文章,0障礙地學習和理解concent狀態管理思路。react

雖然學習和使用過reduxmbox之類的狀態管理庫,閱讀此篇文章會更容易理解,可是沒有使用過任何狀態管理庫的用戶也能極速入門concent,真正的0障礙學會使用它並接入到你的react應用裏。git

注意上面強調了0障礙,包括了學會使用和接入應用兩個方面,爲了達到此目的,api要足夠簡單,簡單到什麼程度呢?簡單到無以復加,簡單到和react保持100%一致,讓新手無需理解額外的概覽,以react組件的編寫方式就能接入狀態管理,可是呢也保留了更高級的抽象接口,讓老手能夠按照redux的模式去組織代碼。github

來吧,展現!本期講解的關鍵api,包括一個3個頂層apirunuseConcentregister,一個實例上下文apisetState,學會使用這4個api,你就已經會使用concent作爲你的狀態管理方案了。json

Hello world

全部的框架都會以Hello world做爲引導,咱們此處也不例外,看看concent版本的Hello world是多麼的簡單。redux

run 定義模塊

concent和redux同樣,有一個全局單一的狀態樹,是一個普通的json對象,不過第一層key規劃爲模塊名,來幫助用戶按照業務場景將狀態切分爲多個模塊,便於分開管理。api

此處咱們須要用到run接口啓動concent並載入模塊配置,配置一個名爲hello的模塊,併爲其定義狀態數組

import { run } from 'concent';

run({
  hello: {
    state: { greeting: 'Hello world' },
  },
});

register 註冊類組件

定義好了模塊,咱們的組件須要消費模塊的狀態,對於類組件,使用register便可架構

import { register } from 'concent';

@register('hello')
class HelloCls extends React.Component{
  state = { greeting: '' };
  changeGreeting = (e)=> this.setState({greeting: e.target.value})
  render(){
    return <input value={this.state.greeting} onChange={this.changeGreeting} />
  }
}

上訴代碼用register接口將HelloCls組件註冊屬於hello模塊,concent將向當前組件this上注入一個實例上下文ctx,用於讀取數據和調用修改方法,同時也默默替換了this上的statesetState,方便用戶能夠0改動原組件的代碼,僅使用register裝飾一下類組件便可接入狀態管理,這就是0障礙學會使用並接入到react應用的基礎,對於初學者來講,你會寫react組件,就已經會使用了concent,沒有任何額外的學習成本。框架

this.state === this.ctx.state; // true
this.setState === this.ctx.setState; // true

上述代碼裏,還聲明瞭一個類成員變量state等於 { greeting: '' },由於greeting和模塊狀態裏的重名了,因此首次渲染以前它的值將被替換爲模塊裏的Hello world,實際上這裏能夠不聲明這個類成員變量state,寫上它只是爲了保證刪除register裝飾器這個組件也能正常工做,而不會獲得一個undefinedgreeting初始值。

useConcent 註冊函數組件

使用useConcent接口註冊當前組件所屬模塊,useConcent會返回當前組件的實例上下文對象ctx,等同於上面類組件的this.ctx,咱們只須要解構它取出statesetState便可。

import { useConcent } from 'concent';

function HelloFn(){
  const { state, setState } = useConcent('hello');
  const changeGreeting = (e)=> setState({greeting: e.target.value})
  return <input value={state.greeting} onChange={changeGreeting} />
}

渲染組件

最後咱們看下完整的代碼吧,咱們發現頂層無Provider之類的組件包裹根組件,由於concent沒有依賴React Context api實現狀態管理,而是本身獨立維護了一個獨立的全局上下文,因此你在已有的項目裏接入concent是很是容易的,即插即用,無需任何額外的改造。

因爲HelloClsHelloFn組件都屬於hello模塊,它們中的任意一個實例修改模塊狀態,concent會將其存儲到store,並同步到其它同屬於hello模塊的實例上,狀態共享就是這麼簡單。

import ReactDOM from 'react-dom';
import { run } from 'concent';
import { register, useConcent } from 'concent';

run({/** 略 */});

@register('hello')
class HelloCls extends React.Component{/** 略 */}

function HelloFn(){/** 略 */}

const App = ()=>(
  <div>
     <HelloCls />
     <HelloFn />
  </div>
);

ReactDOM.render(App, document.getElementById('root'));

點我查看源碼

依賴收集

不管是類組件仍是函數組件,拿到state對象已被轉換爲一個Proxy代理對象,負責收集當前渲染的數據依賴,因此若是是有條件判斷的讀取狀態,推薦採用延遲解構的寫法,讓每一次渲染都鎖定最小的依賴列表,減小冗餘渲染,得到更好的性能。

function HelloFn(){
  const { state, setState, syncBool } = useConcent({module:'hello', state:{show:true}});
  const changeGreeting = (e)=> setState({greeting: e.target.value});
  // 當show爲true時,當前實例的依賴是['greeting'],其餘任意地方修改了greeting值都會觸發當前實例重渲染
  // 當show爲false時,當前實例無依賴,其餘任意地方修改了greeting值不會影響當前實例重渲染
  return (
      <>
    {state.show?<input value={state.greeting} onChange={changeGreeting} />:'no input'}
    <button onClick={syncBool('show')}>toggle show</button>
    </>
  );
}

跨多個模塊消費模塊狀態

當組件須要消費多個模塊的數據時,可以使用connect參數來聲明要鏈接的多個模塊。

使用connect參數鏈接多個模塊

以下面示例,鏈接bar和baz兩個模塊,經過ctx.connectedState獲取目標模塊狀態:

@register({connect:['bar', 'baz']})
class extends React.Component{
  render(){
    const { bar, baz } = this.ctx.connectedState;
  }
}
connectedState拿到的模塊狀態依然存在着依賴收集行爲,因此若是存在條件渲染語句,推薦延遲解構寫法

使用setModuleState修改狀態

經過調用實例上下文apictx.setModuleState修改目標模塊狀態

changeName = e=> this.ctx.setModuleState('bar', {name: e.target.value})

結語

此文僅僅演示了最最基礎的api用法,幫助你快速上手concent,若是你已是老司機,特別是vue3 one piece已宣佈正式發佈的這個關頭,若是你很是的不屑一顧這樣笨拙的代碼組織方式,暫先不要急着否認它,且打開官網看一下其餘特性,必定有你喜歡的亮點,包括爲react 量身定製的composition api,模塊級別的reducercomputedwatchlifecycle等等新特性,後面的速成會一一提到。

Concent攜帶一整套完整的方案,支持漸進式的開發react組件,即不干擾react自己的開發哲學和組件形態,同時也可以得到巨大的性能收益,這意味着咱們能夠至下而上的增量式的迭代,狀態模塊的劃分,派生數據的管理,事件模型的分類,業務代碼的分隔均可以逐步在開發過程勾勒和剝離出來,其過程是絲滑柔順的,也容許咱們至上而下統籌式的開發,一開始吧全部的領域模型和業務模塊抽象的清清楚楚,同時在迭代過程當中也能很是快速的靈活調整而影響整個項目架構.

相關文章
相關標籤/搜索