[react-control-center tutorial 1] cc.startup
react
注:本教程针对的有必定react基础知识的用户,如无任何react只是了解或者开发经验,能够先经过
create-react-app
快速跑起来一个应用并结合官网的知识介绍,再来阅读此文, 对于react开发者能够运行起来quick-start项目作更深的了解gitquick-start demo: github.com/fantasticso…
co
和uuid
,react15和16均可以使用cc和redux最大的不一样之一就是,redux须要在你的顶层App组件以外包裹一个
Provider
组件,用于全局注入和管理redux
的上下文context,对于cc来讲只须要在你定义好cc的启动脚本,而后在你的代码入口文件的第一行里引用改脚本,就能够完成cc的启动工做了,因此使用cc并不会对你现有的代码形成任何入侵,你能够渐进式的在已有项目里局部使用cc,尝试cc的有趣且强大的功能github后续会放出and-design-pro的cc版本,改动的代码不超过100行,就完美将其状态管理框架redux迁移到ccredux
cc支持以模块化的方式和非模块的方式启动起来,若是以非模块的方式启动,cc的store只会有两个内建的模块存在,即
$$global
和$$default
模块,若是以模块化的方式启动,则须要用户显示的划分好模块并做为配置参数交个cc启动让cc按照用户的规划理念启动起来。 启动起来以后:后端
- cc将cc的store绑定到了window.sss下。
- cc将cc的顶层api绑定到window.cc下。
- cc将cc的上下文管理对象绑定到window.ccc下和window.CC_CONTEXT下
用户能够在console里经过sss能够查看当前状态树的最新状态,经过cc直接调用cc提供给开发者的顶层api与各个cc组件产生有趣的互动,这是cc让用户可以体会到cc的强大和有趣的入口之一。
/**-----------------[引入cc启动脚本,让整个项目可以使用cc的全部接口]--------*/
/** code in index.js */
import './startup-cc';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
/**-----------------[不写入任何参数,直接运行cc启动]-----------------------*/
/** code in startup-cc.js */
import cc from 'react-control-center';
cc.startup();
复制代码
cc.startup()
,启动了cc,在正式介绍cc的各类启动方式和区别以前,咱们先来了解一下startup
函数的签名介绍cc.startup(startupOption?:StartupOption);api
- @param
StartupOption.isModuleMode
是否以模块化方式启动cc,默认是false,cc强烈建议用户设置此项为true,方便用户定义更多的模块- @param
StartupOption.store
为cc配置store- @param
StartupOption.reducer
为cc配置reducer,reducer是一堆按模块划分的函数集合,能够是普通函数、生成器函数、async函数,每一cc实例上均可以经过this.$$dispatch派发action对象调用reducer里的函数,修改响应模块里的值- @param
StartupOption.computed
为cc配置computed,这里配置的是模块级别的computed,在cc实例里经过this.$$moduleComputed取到计算后的值- @param
StartupOption.init
为cc配置init,一般是须要从后端获取后再次赋值给store才须要配置此项- @param
StartupOption.sharedToGlobalMapping
为cc配置sharedToGlobalMapping,用户须要把一些模块的值映射到$$global模块时,须要配置此项- @param
StartupOption.moduleSingleClass
为cc配置moduleSingleClass
,标记哪些模块只能注册生成一个ccClass,默认cc容许一个模块注册生成多个cc类
,moduleSingleClass
是一个对象,key为moduleName
,值为布尔值,true就表示这个模块只容许注册一个cc类
你们能够先对这些这些参数有个印象,阅读后面的讲解再逐步理解透这里面每个参数的具体做用
非模块化启动,cc会内置两个模块
$$default
、$$global
一个模块必定包含state
,reducer
、init
、computed
是可选项,根据用户的实际状况考虑是否配置bash
非模块方式一般适用于小规模的应用,状态划分简单,边界清晰,智能组件较少,开发时对状态的修改都比较清晰,业务上这些组件的领域分类不是很明显,例如基于react写一个表单提交(固然这只是举例,一般一个表单就不须要写成一个单页面应用了,可是若是是写一个生成通用表单的平台,为了方便维护和扩展,享受现代js开发ui带来的友好体验,开发者一般仍是会选择一个ui库和状态管理库)app
/**-----------------[引入cc启动脚本,让整个项目可以使用cc的全部接口]--------*/
/** code in index.js */
import './startup-cc';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
/**-----------------[不写入任何参数,直接运行cc启动]-----------------------*/
/** code in startup-cc.js */
import cc from 'react-control-center';
// 缺省参数启动cc,cc会默认生成两个模块$$default、$$global
cc.startup();
// 在console里输入sss, 能够查看到状态树形如: {$$default:{}, $$global:{}}
复制代码
$$global
模块和$$default
模块启动经过上面咱们知道以非模块化方式启动cc时,cc会自动建立2个模块
$$default
、$$global
,可是cc也容许用户显示的申明两个模块的值, 为StartupOption.store
配置一个初始化的状态树
当用户显示的把store的key写为global或者default任意之一时,cc把store的key当作模块名,将global或者default对应的对象赋值给cc对应global模块或者default模块的状态树,其余多余的key会被cc警告用户使用模块化方式启动才能识别,可是cc只会警告用户,而后忽略这key的值启动起来框架
/**-----------------[规划模块参数启动cc]----------------------------------*/
/** code in startup-cc.js */
import cc from 'react-control-center';
// 经过上面咱们知道以非模块化方式启动cc时,cc会自动建立2个模块$$default、$$global
// 可是cc也容许用户显示的申明两个模块的值, StartupOption.store 为cc初始化一个状态树
// 当用户显示的把store的key写为$$global或者$default任意之一时,cc把store的key当作
// 模块名,将$$global或者$$default对应的对象赋值给cc对应$$global模块或者$$default
// 模块的状态树,其余多余的key会被cc警告用户使用模块化方式启动才能识别,可是cc只会警告
// 用户,而后忽略这key的值启动起来
cc.startup({
store:{
$$global:{
themeColor:'pink',
module:'pink',
},
$$default:{
foo:'foo',
bar:'bar'
},
thisModuleWillBeenIgnored:{// 这对于cc来讲是一个无效的模块声明
foo:'foo',
}
}
});
// 若是store直接赋值一个普通对象,不包含任何名字为$$default、$$global的key,cc默认
// 将这个对象处理为$$default模块的对象
cc.startup({
store:{
themeColor:'pink',
module:'pink',
}
});
复制代码
$$global
模块和$$default
模块启动,为$$global
模块配置reducer
、init
、computed
/** code in startup-cc.js */
import cc from 'react-control-center';
cc.startup({
store:{
$$global:{
themeColor:'',
module:'pink',
bonus:0,
recommendedLink:'',
},
$$default:{
foo:'foo',
bar:'bar'
}
},
reducer:{
$$global:{
changeThemeColor:function* ({payload:{userId, color}}){
// 修改主题色,用户得到积分
const bonus = yield api.changeThemeColor({userId, color});
return {bonus};
},
recoverOriginalThemeColor:async function({payload:{userId}, dispatch}){
// 恢复最初的主题色,各一个推荐连接
const recommendedLink = yield api.recoverOriginalThemeColor({userId});
dispatch({reducerModule:'whatever',type:'trackUser', payload:'wow wow'});
return {recommendedLink};
}
},
// 注意此处申明了whaterver当作模块值,可是whaterver并无在store里声明过,cc是容许用户这样作的,由于cc认为recuder能够有本身的模块划分定义,实际上当用户在cc实例里调用dispatch时,
// 会形如this.$$dispatch({reducerModule:'whatever',type:'trackUser',payload:'cool'})这样,
// cc会找到对应reducer模块whatever的type为trackUser的函数去执行数据修改逻辑,
// this.$$dispatch里不指定reducerModule,默认会找Action对象里指定的module当作reducerModule,
// Action对对象里没有指定module,会把当前cc实例所属的module当作reducerModule
whaterver:{
trackUser: function*(){
// ... ...
}
}
},
init:{
$$global:setState=>{
api.getInitThemeColor(themeColor=>{
setState({themeColor});
})
}
},
computed:{
$$global:{
themeColor(themeColor){// 当themeColor发生变化时,计算新的值,cc实例里的this.$$globalComputed.themeColor能够取到
return {spanBorder:`2px solid ${themeColor}`, pBorder:`8px solid ${themeColor}`};
}
},
$default:{
foo(foo){// 反转foo字符串, cc实例里this.$$moduleComputed.foo能够取到改计算值
return foo.split('').reverse().join('');
}
}
}
});
复制代码
须要在StartOption显示的设定
isModuleMode
为true,其余方式和上面的非模块的方式同样,惟一不一样的是cc容许你使用其余名字做为模块名了,还容许你自定义StartOption.sharedToGlobalMapping
将某些模块里的某些key起个别名映射到$$global
模块里.
cc提供sharedToGlobalMapping
是由于在cc世界里,一个cc类只能观察注册的所属模块的状态变化(即一个cc类直属于一个模块),可是全部cc类都可以观察global模块的转态变化,当cc类须要观察其余模块的某些key的状态变化时,须要那个模块先将它的这些key映射到$$global
里,而后cc类观察映射到$$global
里的这些key,就达到了一个cc类
能够观察多个模块变化的目的dom
/** code in startup-cc.js */
import cc from 'react-control-center';
cc.startup({
store:{
$$global:{
themeColor:'',
module:'pink',
bonus:0,
recommendedLink:'',
},
$$default:{
foo:'foo',
bar:'bar'
},
foo:{
f1:'f1',
f2:'f2',
},
bar:{
f1:'f1',
f2:'f2',
}
},
//其余配置略 .......
// 映射时注意命名冲突
sharedToGlobalMapping:{
// 如下配置将foo模块的f一、f2字段映射到$$global里,由于$$global没有名字为f一、f2的字段,这里就再也不起别名了
foo:{
f1:'f1',
f2:'f2',
},
// 如下配置将bar模块的f一、f2字段映射到$$global里分别为bf一、bf2,由于$$global模块里已经存在了f1,f2,因此这里起了别名
bar:{
f1:'bf1',
f2:'bf2',
}
}
}
复制代码
startup
的解释相信很多读者必定还有疑问,由于提早提到了一些后面还会进一步详细解释的名词概念,
- 好比配合讲解
reducer
时提到了cc实例的$$dispatch
,- 配合讲解
sharedToGlobalMapping
时,提到了观察多个模块状态变化,cc除了使用sharedToGlobalMapping
达到观察多个模块状态变化的目的,还提供更强大的方式,注册为cc类时候声明stateToPropMapping
,能够不用把目标观察模块的key映射到$$global
就可以观察其余模块的状态变化,后面会作详解- 提到了一个
模块
能够注册多个cc类
,整个cc世界里,cc类
、react类
、和模块
的关系会以下图,你们能够先作简单了解,后面再回顾此图会理解更深
quick-start demo: github.com/fantasticso…