写前面
自从听闻React出世后那阵子 就学了相关的知识 可是一直没有机会实践过! 都已经过了大半年了 再不操刀 可不行!
下面的demo 可以说canvas 来做比较靠谱 但是!
我就要用dom来实现 咱的目的是来实践React的 !
------------------------------------------------------------
效果图:
我们将界面分解成组件形式
这些组件外面 还有个包裹他们的 MotionSegment组件
------------------------------------------------------------
代码的基础结构:
初始化
1 import MotionSegment from ‘./MotionSegment‘; 2 3 _$(()=>{ 4 5 const c = _$.color(‘rgb‘,{to_number:1}); 6 7 const prop = { 8 sgm_head : { 9 radius : 50 10 ,color : c 11 } 12 ,sgm_body : { 13 nums : 23 14 ,width : 5 15 ,height : 1 16 ,color : c 17 } 18 ,cir_enemy :{ 19 radius : 80 20 ,nums : 10 21 } 22 }; 23 24 React.render( 25 <MotionSegment {...prop}/> 26 ,_$(‘#place‘)[0] 27 ); 28 29 });
传递参数对象给MotionSegment 再渲染到#place元素中
MotionSegment 组件
import SegmentControl from ‘./SegmentControl‘; import CirEnemyControl from ‘./CirEnemyControl‘; import ScoreBoard from ‘./ScoreBoard‘; import Ev from ‘./Ev‘; const MotionSegment = React.createClass({ render(){ //..... return ( <div style={c}> <SegmentControl sgm_head={this.props.sgm_head} sgm_body={this.props.sgm_body} mouse={this.state.mouse} /> <CirEnemyControl {...this.props.cir_enemy} t={this.state.t}/> <ScoreBoard nums={this.props.cir_enemy.nums}/> </div> ) } //... }); export default MotionSegment;
MotionSegment 含有3个子组件 SegmentControl CirEnemyControl ScoreBoard
*有个Ev 全局对象 这个用来控制组件之间的通信用 组件通信有几种方法 。如 传callback 、context 、还有redux等。。
我选用 订阅/发布模式 做通信 ,对于这个demo足够用!
redux 适合大型的应用 ,其他几种我不喜欢= =
SegmentControl组件
import SegmentHead from ‘./SegmentHead‘; import SegmentBody from ‘./SegmentBody‘; const SegmentControl = React.createClass({ render(t){ //... return( <div> <SegmentHead {...this.props.sgm_head} mouse={this.props.mouse}/> <SegmentBody {...this.props.sgm_body} mouse={this.props.mouse}/> </div> ) } //... }); export default SegmentControl;
SegmentHead组件
import Ev from ‘./Ev‘; const Ev_Type = { ‘sh/pos‘ : ‘SegmentHead/pos‘ }; const SegmentHead = React.createClass({ render(){ //... return ( <div style={stys}></div> ) } //... }); export default SegmentHead;
SegmentBody组件
import Segment from ‘./Segment‘; const SegmentBody = React.createClass({ render(){ //... return ( <div> { body_data.map((v,i)=>{ return <Segment key={i} {...body_data[i]} height={height}/> }) } </div> ) } //... }); export default SegmentBody;
Segment组件
const Segment = React.createClass({ render(){ //... return( <div style={stys}></div> ) } //... }); export default Segment;
CirEnemyControl组件
import Ev from ‘./Ev‘; import CirEnemy from ‘./CirEnemy‘; const Ev_Type = { ‘sh/pos‘ : ‘SegmentHead/pos‘ ,‘ce/pos‘ : ‘CirEnemy/pos‘ ,‘cec/addScore‘ : ‘CirEnemyControl/addScore‘ ,‘cec/success‘ : ‘CirEnemyControl/success‘ } const CirEnemyControl = React.createClass({ render(){ //.... // return( <div> { pos_data.map((data,i)=>{ return <CirEnemy key={i} i = {i} t={this.props.t} {...data} /> }) } </div> ) } //... }); export default CirEnemyControl;
CirEnemy组件
import Ev from ‘./Ev‘; const Ev_Type = { ‘ce/pos‘ : ‘CirEnemy/pos‘ ,‘ce/click‘ : ‘CirEnemy/click‘ }; const CirEnemy = React.createClass({ //... render(){ return( <div style={stys}></div> ) } //... }); export default CirEnemy;
最后个计分的ScoreBoard
import Ev from ‘./Ev‘; const Ev_Type = { ‘cec/addScore‘ : ‘CirEnemyControl/addScore‘ ,‘cec/success‘ : ‘CirEnemyControl/success‘ } const ScoreBoard = React.createClass({ //... render(){ var s = `${this.state.score}/${this.props.nums}`; this.state.complete && (s=‘都被你吃完啦~‘); return( <h1 style={this.props.stys}>{s}</h1> ) } //... }); export default ScoreBoard;
大致结构就上面这样子了~
-------------------------------------------
有几个的关键的地方讲讲
1 组件之间如何通信的?
2 渲染何时进行的?
3 那个长的像蛇的是怎么做的? dom都能做?
1、关于通信 一开始我用的传统callback传递来实现父子和姐妹之间的通信。。后面发现套了2层就挺烦了 之后又试了其余几种 决定还是用订阅发布靠谱
接受消息我统统放到componentDidMount 之中 比如 在记分组件 具体就在
import Ev from ‘./Ev‘; const Ev_Type = { ‘cec/addScore‘ : ‘CirEnemyControl/addScore‘ ,‘cec/success‘ : ‘CirEnemyControl/success‘ } //... const ScoreBoard = React.createClass({ //... ,componentDidMount(){ Ev.on(Ev_Type[‘cec/addScore‘],this.onAddScore); Ev.on(Ev_Type[‘cec/success‘],this.onSuccess); } }); export default ScoreBoard;
CirEnemyControl如果发布了消息 ScoreBoard就会接受到了。
2、在根组件MotionSegment 开个主循环 实时的传递鼠标坐标位置和时间戳 渲染工作也顺便做了。。
,componentDidMount(){ const T = _$.Timer; //... T.execute(); T.loop(t=>{ this.setState({ mouse : mouse ,t : t }); }); //... }
3、这个玩意属于骨骼动画了 用canvas做靠谱 这里是用dom实现的 有了些多余的计算 主要是处理身体部分 其实就是N个节段的组合 利用上个节段的坐标位置 递归计算 需要点处理技巧。。
我之后专门放到canvas里去讨论 此篇主要是来实践React的 先不说~~~
*React实践还很少 不能说写的有多好 但终归完成了
有不对 或不严谨的地方 恳请指正!