Concent
made with React

简介及使用教程

Concent是一个内置依赖收集,可预测、0入侵、渐进式、高性能的react开发框架,是一个渐进式&高性能的react数据流方案。

Concent通过为函数组件和类组件注入一致的实例上下文并代理状态,实现了高效的运行时依赖收集机制,并允许以组合api的方式来完成这两种组件的逻辑书写统一(包括生命周期),同时友好的模块定义方式(state,reducer,computed,watch,lifecycle)让我们可以弹性灵活地搭建更友好和健壮的项目架构。

特性

  • 极简的核心apirun载入模块配置启动concent,register注册组件,无需包一层Provider在根组件。
  • 0入侵成本接入,不改造代码的情况下直接接入;hello-concent
  • 贴心的模块配置,除了state,还提供reducercomputedwatchinit四项可选定义。
  • 灵活的数据消费粒度,支持跨多个模块场景,以及模块内stateKey级别的细粒度控制。
  • 渐进式构建react应用,除了setState,支持dispatchinvoke调用来让ui视图与业务逻辑彻底解耦。从class到function
  • 组件能力增强,支持实例级别computedwatch定义,支持emit&on,以及支持setup特性,让函数组件拥有定义静态api的能力。
  • 高度一致的编程体验hocrender propshook3种方式定义的组件均享有一致的api调用体验,相互切换代价为0。多种方式定义组件
  • 渲染性能出众,内置renderKeylazyDispatchdelayBroadcast等特性,保证极速的渲染效率。长列表精准渲染批处理状态提交高频输入场景状态延迟分发
  • 干净的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>
  );
}

r5.gif

完整示例

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?

image.png

基于中间件插件机制,你可以很容易的抽象和定制非业务相关的处理器,或者迁移redux生态相关库。

image.png

作者

cencentjs

相关项目

这是一个快速反应的静态站点生成器。
这是一个基于React和Redux的轻量级JavaScript框架
这是一个全栈React + GraphQL框架。
这是一个无​​服务器的内容管理系统(CMS)。
这是一个React的Material设计风格的组件库。
这是一个基于Microsoft的UWP和Fluent Design的组件库。