concent是一个专为react
提供状态管理服务的框架,重新定义state
和component
之间的关系,同时也为你的react
组件提供更多有趣且强大的特性,保持渲染性能最优化,让你专注于业务代码编写😎,让你的react
工程代码变得更加简约、优雅,并容易维护与扩展。
- 核心api少且简单,功能强大,上手容易,入侵小,容易调试;
- 提供全局模块化的单一数据源;
- 共享数据可直接注入到state,也可注入props,点我查看。
- 修改共享数据的方式灵活多样且简单直接,点我查看;
- 对组件扩展了事件总线、computed、watch、双向绑定等特性,点我查看;
- 内置与react16一样的使用方式但却更有趣的hook,点我查看;
- 默认采用反向继承包裹你的组件,让react dom tree层级更少,保持干净和清爽;
- 基于引用定位和状态广播,支持细粒度的状态订阅,渲染效率出众,点我查看;
- 支持中间件,可以扩展你的个性化插件处理数据变更,点我查看;
- 支持react 0.10+任意版本;
请移步阅读和了解react-router-concent,搭配使用非常的简单和容易。
确保你本地机器上安装有nodejs。
在你的电脑上,选择一个合适的目录并进入,使用create-react-app 创建一个app
$ npm i -g create-react-app
$ create-react-app cc-app
创建好app后,进入你的app根目录,使用npm安装concent
$ cd cc-app
$ npm i --save concent
或者使用yarn安装
$ yarn add concent
将以下代码复制粘贴到cc-app
目录下的src/App.js
文件里(注:是完全覆盖掉原来的内容)。
- 运行concent,载入模块配置
import React, { Component, Fragment } from 'react';
import { register, run } from 'concent';
run({
counter: {//定义counter模块
state: {//定义state
count: 0,
},
reducer: {
inc(payload, moduleState) {
return { count: moduleState.count + 1 };
},
dec(payload, moduleState) {
return { count: moduleState.count - 1 };
}
}
}
})
- 基于react class注册成为cc类组件
class Counter extends Component {
//setState 能够将数据将同步到store,广播到其他实例
inc = () => {
this.setState({ count: this.state.count + 1 });
}
dec = () => {
this.setState({ count: this.state.count - 1 });
}
//调用dispatch, 同样的能够将数据将同步到store,广播到其他属于counter模块或者连接到counter模块的实例
incD = () => {
this.ctx.dispatch('inc');
}
decD = () => {
this.ctx.dispatch('dec');
}
render() {
//concent注入counter模块的数据到state
const { count } = this.state;
return (
<div style={{ padding: '12px', margin: '6px' }}>
<div>count: {count}</div>
<button onClick={this.inc}>inc by setState</button>
<button onClick={this.dec}>dec by setState</button>
<br />
<button onClick={this.incD}>inc by dispatch</button>
<button onClick={this.decD}>dec by dispatch</button>
</div>
);
}
}
//将Counter类注册为CcClazzCounter,属于counter模块
const CcClazzCounter = register('counter')(Counter);
- 基于renderProps注册为cc类组件
import { registerDumb } from 'concent';
const UI = ({count, inc, dec, incD, decD})=>{
return (
<div style={{ padding: '12px', margin: '6px' }}>
<div>count: {count}</div>
<button onClick={inc}>inc by setState</button>
<button onClick={dec}>dec by setState</button>
<br />
<button onClick={incD}>inc by dispatch</button>
<button onClick={decD}>dec by dispatch</button>
</div>
);
}
//定义setup,该函数只会在ui初次渲染前执行一次,通常用于定义一些方法,结果会收集到ctx.settings里
const setup = ctx=>{
const inc = () => {
ctx.setState({ count: ctx.state.count + 1 });
};
const dec = () => {
ctx.setState({ count: ctx.state.count - 1 });
};
const incD = () => {
ctx.dispatch('inc');
};
const decD = () => {
ctx.dispatch('dec');
};
return {inc, dec, incD, decD};
}
//定义mapProps,该函数在ui每次渲染前被执行,结果将映射到组件的props上
const mapProps = ctx=>{
return {count:ctx.state.count, ...ctx.settings};
}
//将Counter类注册为CcFnCounter,属于counter模块
const CcFnCounter = registerDumb({module:'counter', setup, mapProps})(UI);
--- 基于hook注册为组件
import { useConcent } from 'concent';
function HookCounter(){
const {state, setState, dispatch} = useConcent('counter');
const inc = () => {
setState({ count: ctx.state.count + 1 });
};
const dec = () => {
setState({ count: ctx.state.count - 1 });
};
const incD = () => {
dispatch('inc');
};
const decD = () => {
dispatch('dec');
};
return (
<div style={{ padding: '12px', margin: '6px' }}>
<div>count: {count}</div>
<button onClick={inc}>inc by setState</button>
<button onClick={dec}>dec by setState</button>
<br />
<button onClick={incD}>inc by dispatch</button>
<button onClick={decD}>dec by dispatch</button>
</div>
);
}
--- 更优的hook写法,将函数提升为静态api
import { useConcent } from 'concent';
//同样的,该函数只在ui首次渲染前被执行一次!!!
const setup = ctx =>{
const {state, setState, dispatch} = ctx;
const inc = () => {
setState({ count: ctx.state.count + 1 });
};
const dec = () => {
setState({ count: ctx.state.count - 1 });
};
const incD = () => {
dispatch('inc');
};
const decD = () => {
dispatch('dec');
};
return {inc, dec, incD, decD};
}
function HookCounter(){
const {settings, state} = useConcent({module:'counter', setup});
const {inc, dec, incD, decD} = settings;
return (
<div style={{ padding: '12px', margin: '6px' }}>
<div>count: {state.count}</div>
<button onClick={inc}>inc by setState</button>
<button onClick={dec}>dec by setState</button>
<br />
<button onClick={incD}>inc by dispatch</button>
<button onClick={decD}>dec by dispatch</button>
</div>
);
}