视图与事务,好一对冤家

事务型model

model是需求精心的规划和合理的区分的,这是咱们之前开发大型的redux+react单页面运用,咱们都认同的真理,同样的,在react-control-center+react的开发里也适用这条黄金规则,一般,咱们在接到需求,定制开发方案的时分,会抽象出许多事务相关的关键词,这些关键词渐渐经过进一步整理,将成为咱们区分功用或许模块的有效根据,这些模块最终在前端这里会沉积为model,每一个model界说了自己的statereducer,当然如果有需求,还可认为其界说computedinit,经过精心的目录组织和规范的约好,视图的烘托逻辑和咱们书写的事务逻辑被有效的解耦到component里和reducer里,这样当咱们需求重构UI组件,能够定心的对其重构或许新增一个组件,复用相同的statereducer
参阅cc-antd-pro的区分

|________layouts
|     |________BasicLayout.js
|     |________BasicLayout.less
|     |________BlankLayout.js
|     |________PageHeaderLayout.js
|     |________PageHeaderLayout.less
|     |________UserLayout.js
|     |________UserLayout.less
|________models
|     |________activities.js
|     |________chart.js
|     |________form.js
|     |________global.js
|     |________index.js
|     |________list.js
|     |________login.js
|     |________monitor.js
|     |________profile.js
|     |________project.js
|     |________register.js
|     |________rule.js
|     |________user.js

视图型model

有一些状况,咱们开发的过程中,发现和视图紧密相关,不同的组件在不同的生命周期阶段,都需求运用他们或许感知到他们的改变,例如右上角用户勾选的主题色,影响左下角一个抽屉的弹出策略或效果,这些状况同样需求交个状况办理结构集中办理起来,所以咱们也会这些需求规划相应的model,这一类和主要事务逻辑不想管,但是咱们仍然需求精心办理起来的model,咱们称之为视图型model.

视图代码膨胀之困惑

一般,咱们已开端精心规划好各种model后,开端决心满满的进入开发流程,跟着功用迭代越来越块,需求改变越来频繁,咱们的model会不断的调整或许扩展,按照class组件和function组件份额2:8开的准则,咱们总是想抽出更多的function组件,class组件担任和和model打通,然后从model里拿到的数据层层派发它的所以孩子function组件里,但是function组件一般都不是只担任展现,仍是有不少function组件需求修改modelstate,所以咱们在ant-design-pro里或许其他地方,仍然会看到不少类似代码

@connect(state => ({
  register: state.register,
}))
class Foo extends Component {
    render(){
        return (
            <MyStatelessFoo {...this.props}/>
        );
    }
}
const MyStatelessFoo = ({dispatch}){
    return <div onClick={dispatch('foo/changeSomething')}>whaterver</div>
}

如果有function组件Foo1Foo2Foo3,Foo1嵌套Foo2,Foo2嵌套了Foo3,看起来要一层一层传递下去了。
一起视图组件调整的时间占比会远大于reducer函数的书写,咱们有时分为了那个某个modelstate,不断的传递下去或许渐渐的将某些比较重的function组件又提升为class组件

react hooks处理了什么呢?

这里复制一段facebook引出hooks要处理的问题所在之处

  • 难以重用和共享组件中的与状况相关的逻辑
  • 逻辑复杂的组件难以开发与维护,当咱们的组件需求处理多个互不相关的 local state * 时,每个生命周期函数中可能会包含着各种互不相关的逻辑在里面。
  • 类组件中的this添加学习本钱,类组件在根据现有东西的优化上存在少许问题。
  • 由于事务改变,函数组件不得不改为类组件等等。

可是如果咱们的function组件如果是需求共享或许修改modelstate呢,有什么更优雅的办法处理吗?

CcFragment为你带来全新的无状况组件书写体验

一个典型的CcFragment运用办法如下

import {CcFragment} from 'react-control-center';
//在你的一般的react组件或许cc组件里,都能够写如下代码
  render() {
    <div>
      <span>another jsx content</span>
      <hr/>
      <CcFragment ccKey="toKnowWhichFragmentChangeStore" connect={{ 'foo/*': '', 'bar/a': 'a', 'bar/b': 'alias_b' }}>
        {
          ({ propState, setState, dispatch, emit, effect, xeffect, lazyEffect, lazyXeffect }) => (
            <div onClick={() => setState('foo', { name: 'cool, I can change foo module name' })}>
              {/* 以上办法,你能够像在cc类组件相同的运用它们,没有差异 */}
              {propState.foo.name}
              {propState.bar.a}
              {propState.bar.alias_b}
            </div>
          )
        }
      </CcFragment>
    </div>
  }

上面代码里,CcFragment标记一个ccKeyconnect

  • cc默认是会为一切CcFragment主动生成ccKey的,但是咱们引荐你书写一个有意义的ccKey,因为CcFragment答应无状况组件直接运用setState, dispatch, emit, effect, xeffect, lazyEffect, lazyXeffect办法去修改状况或许建议通知,这些函数的运用体验是和cc class一摸相同,加上ccKey,你能够在你的中间件函数里看到某一次的状况改变是由哪一个ccKey触发的,这样未来你能够在还在方案开发中的cc-dev-tool里检查具体的状况变迁前史,当然现在你需求检查状况改变的话,能够写一个简略的中间件函数来log
function myMiddleware(params, next) {
  //params 里你能够看到本次状况改变提交的状况是什么,由什么办法触发,由那个ccKey的引用触发等
  console.log('myMiddleware', params);
  next();
}
cc.startup({
  //...
  middlewares: [myMiddleware]
});
  • connect和cc.registercc.connect相同,表明该CcFragment关注那些模块,哪些值的改变,上述示例的效果会是

1 只要bar模块的a或许b改变了,都会触发该CcFragment的烘托
2 只要foo模块的任意key改变了,都会触发该CcFragment的烘托
3 点击了div,会去修改foo模块的name值,关注foo模块name值改变的一切cc组件或许CcFragment组件都会触发烘托

所以CcFragment处理了用户在无状况组件里共享了model数据的问题,你写的无状况组件很容易和cc store打通,而无需在考虑抽取为cc class组件,CcFragment本质上和hooks不存在冲突办理,也和现有cc class不冲突,只是作为cc世界里更重要的弥补,让你能够无损的运用现有的function组件。
注意一点哦,CcFragment本身是不会因为父组件的更新而被更新的哦,仅仅受操控于connect参数观察的参数是否发生改变,所以它的烘托仍然是高效的。

那么心爱的各位看官,还不赶紧运用起来

  • 在线示例点我
  • cc版别ant-design-pro
  • 基础入门项目
  • runjs录像教程