Concent
made with
React
Concent
这是一个可预测、0入侵、渐进式、高性能的react开发框架。
简介及使用教程
Concent是一个内置依赖收集,可预测、0入侵、渐进式、高性能的react开发框架,是一个渐进式&高性能的react数据流方案。
Concent通过为函数组件和类组件注入一致的实例上下文并代理状态,实现了高效的运行时依赖收集机制,并允许以组合api的方式来完成这两种组件的逻辑书写统一(包括生命周期),同时友好的模块定义方式(state,reducer,computed,watch,lifecycle)让我们可以弹性灵活地搭建更友好和健壮的项目架构。
特性
- 极简的核心api,
run
载入模块配置启动concent,register
注册组件,无需包一层Provider
在根组件。 - 0入侵成本接入,不改造代码的情况下直接接入;hello-concent
- 贴心的模块配置,除了
state
,还提供reducer
、computed
、watch
和init
四项可选定义。 - 灵活的数据消费粒度,支持跨多个模块场景,以及模块内stateKey级别的细粒度控制。
- 渐进式构建react应用,除了
setState
,支持dispatch
、invoke
调用来让ui视图与业务逻辑彻底解耦。从class到function - 组件能力增强,支持实例级别
computed
、watch
定义,支持emit&on
,以及支持setup
特性,让函数组件拥有定义静态api的能力。 - 高度一致的编程体验,
hoc
、render props
和hook
3种方式定义的组件均享有一致的api调用体验,相互切换代价为0。多种方式定义组件 - 渲染性能出众,内置
renderKey
、lazyDispatch
、delayBroadcast
等特性,保证极速的渲染效率。长列表精准渲染、批处理状态提交、高频输入场景状态延迟分发 - 干净的dom层级,对于class组件,默认采用反向继承策略,让react dom树的层级结构保持简洁与干净。
- 扩展中间件与插件,允许用户定义中间件拦截所有的数据变更提交记录,做额外处理,也可以自定义插件,接收运行时的发出的各种信号,按需增强concent自身的能力。
- 去中心化配置模块,除了
run
接口一次性配置模块,还提供configure
接口在任意地方动态配置模块。 - 模块克隆,支持对已定义模块进行克隆,满足你高维度抽象的需要。
- 完整的typescript支持,能够非常容易地书写优雅的ts代码。
安装
NPM
npm i --save concent
Yarn
yarn add concent
简单示例
import { run, register, useConcent } from 'concent';
run({
counter: {// 声明一个名为'counter'的模块
state: { num: 1, numBig: 100 }, // 定义状态
},
//你也可以在这里继续声明或添加其他模块
});
@register('counter')
class DemoCls extends React.Component{
// 此时setState提交的状态触发自己重渲染
// 同时也会触发其他同样属于coutner模块的实例且消费了具体数据的实例重渲染
inc = ()=> this.setState({num: this.state.num + 1})
render(){
// 这里读取了num,意味着当前实例的依赖key列表是 ['num']
return <button onClick={this.inc}>{this.state.num}</button>
}
}
function DemoFn(){
const { state, setState } = useConcent('counter');
const inc = ()=> setState({num: state.num + 1});
return <button onClick={inc}>{state.num}</button>
}
export default function App(){
return (
<div>
<ClsComp />
<FnComp />
</div>
);
}
完整示例
import { run, register, useConcent, defWatch } from 'concent';
run({
counter: {
state: { num: 1, numBig: 100 },
computed: {
numx2: ({ num }) => num * 2, //仅当num改变是才触发
numx2plusBig: ({ numBig }, o, f) => f.cuVal.numx2 + numBig // 重用计算结果
},
reducer: {
initState: () => ({ num: 8, numBig: 800 }),
add: (payload, moduleState, actionCtx) => ({ num: moduleState.num + 1 }),
addBig: (p, m, ac) => ({ numBig: m.numBig + 100 }),
asyncAdd: async (p, m, ac) => {
await delay(1000);
return { num: m.num + 1 };
},
addSmallAndBig: async (p, m, ac) => {
// hate string literal? see https://codesandbox.io/s/combine-reducers-better-7u3t9
await ac.dispatch("add");
await ac.dispatch("addBig");
}
},
watch: {
numChange: defWatch(({ num }, o) => console.log(`from ${o.num} to ${num}`), {immediate:true})
},
lifecycle: {
// loaded: (dispatch) => dispatch("initState"), // 模块加载时触发
mounted: (dispatch) => dispatch("initState"), // triggered when the first ins of counter module mounted
willUnmount: (dispatch) => dispatch("initState") // triggered when the last ins of counter module unmount
}
}
});
@register("counter")
class DemoCls extends React.Component {
render() {
// mr is short of moduleReducer, now you can call counter module's all reducer fns by mr
return <button onClick={this.ctx.mr.add}>{this.state.num}</button>;
}
}
function DemoFn() {
const { moduleComputed, mr } = useConcent("counter");
return <button onClick={mr.add}>numx2plusBig: {moduleComputed.numx2plusBig}</button>;
}
架构图
How concent component ins works?
基于中间件和插件机制,你可以很容易的抽象和定制非业务相关的处理器,或者迁移redux
生态相关库。
作者
cencentjs
相关项目