开源不易,感激你的反对,❤ star concent^_^
序言
[Concent 速成]是一个帮忙老手极速入门 concent
的系列文章,0 阻碍地学习和了解 concent 状态治理思路。
尽管学习和应用过 redux
和mbox
之类的状态治理库,浏览此篇文章会更容易了解,然而没有应用过任何状态治理库的用户也能极速入门 concent
,真正的 0 阻碍 学会应用它并接入到你的 react 利用里。
留神下面强调了 0 阻碍,包含了学会应用和接入利用两个方面,为了达到此目标,api 要足够简略,简略到什么水平呢?简略到变本加厉,简略到和react
放弃 100% 统一,让老手无需了解额定的概览,以 react 组件的编写形式就能接入状态治理,然而呢也保留了更高级的形象接口,让新手能够依照 redux
的模式去组织代码。
来吧,展现!本期解说的要害 api,包含一个 3 个顶层 apirun
、useConcent
、register
,一个实例上下文 apisetState
,学会应用这 4 个 api,你就曾经会应用 concent 做为你的状态治理计划了。
Hello world
所有的框架都会以 Hello world
作为疏导,咱们此处也不例外,看看 concent
版本的 Hello world
是如许的简略。
run 定义模块
concent 和 redux 一样,有一个全局繁多的状态树,是一个一般的 json 对象,不过第一层 key 布局为模块名,来帮忙用户依照业务场景将状态切分为多个模块,便于离开治理。
此处咱们须要用到 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 上的state
和setState
,不便用户能够 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
装璜器这个组件也能失常工作,而不会失去一个 undefined
的greeting
初始值。
useConcent 注册函数组件
应用 useConcent
接口注册以后组件所属模块,useConcent
会返回以后组件的实例上下文对象 ctx
,等同于下面类组件的this.ctx
,咱们只须要解构它取出state
和setState
即可。
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 是非常容易的,即插即用,无需任何额定的革新。
因为 HelloCls
和HelloFn
组件都属于 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,模块级别的 reducer
、computed
、watch
、lifecycle
等等新个性,前面的速成会一一提到。
Concent 携带一整套残缺的计划,反对 渐进式 的开发 react 组件,即不烦扰 react 自身的开发哲学和组件状态,同时也可能取得微小的性能收益,这意味着咱们能够至下而上的增量式的迭代,状态模块的划分,派生数据的治理,事件模型的分类,业务代码的分隔都能够逐渐在开发过程勾画和剥离进去,其过程是丝滑柔顺的,也容许咱们至上而下兼顾式的开发,一开始吧所有的畛域模型和业务模块形象的清清楚楚,同时在迭代过程中也能十分疾速的灵便调整而影响整个我的项目架构.