Hello, plume2.

import React, { Component } from 'react'import {Actor,Store,StoreProvider,Relax,ViewAction} from 'plume2'//MapReduce  class HelloActor extends Actor{    defaultState(){        return {text:"Hello,plume2"}    }}//reactive ui event 反应式ui事件class AppViewAction extends ViewAction{    sayHello = (text:any) =>{        this.store.dispatch('say:hello',text)    }}// Single Data Source 繁多数据源class AppStore extends Store{    //bind data transform 绑定数据转换    bindActor(){        //after plume2   directly pass Actor class 间接通过Actor类        return [HelloActor]    }    //bind ui event 绑定ui事件    bindViewAction(){        return {            AppViewAction        }    }}//Auto compute relaxProps 主动计算关上Props@Relax  class Text extends React.Component{    static relaxProps = {        //auto injected by store.state().get('text')  由store.state().get('text')主动注入        text:"text",        //auto injected by store's bindViewAction 由store的bindViewAction主动注入        ViewAction:'viewAction'    }    _handleClick = () =>{        const {text,viewAction} = this.props.relaxProps        viewAction.AppViewAction.sayHello(text)    }    render(){        const {text,viewAction} = this.props.relaxProps;        return (            <div onClick={this._handleClick}>{text}</div>        )    }}@StoreProvider(AppStore) //应用程序入口export default class Index extends Component {    render() {        return (            <div>                <Text/>            </div>        )    }}

API Actor

Actor 计算模型,一个独立的计算单元,次要作用就是转换咱们的状态数据

import { Actor,Action} from 'plume2'// 是的  这就是一个Actor简略世界class HelloActor extends Actor{    // 畛域的初始数据  该数据会被主动的转换为immutable    defaultState(){        // 返回的对象会被主动的转化为immutable        // 除非有非凡数据结构如(set OrderedMap之类)        //不须要非凡指定immutable数据结构        return {text:'hello plume2'}    }    //**  通过@Action来建设store的dispatch和actor的handler(处理程序)之间的关联    // API标准    // @param state actor上一次的immutable状态    // @param text  store dispatch的参数值  尽量放弃单值设计    @Action('change:text')    change(state,text){        // immutable api        return state.set('text',text)    }}

Store

什么是 Store?
Store 咱们的数据状态容器核心 治理着整个app的数据的生命周期
咱们坚守单根数据源的思维(single data source),store 中放弃着残缺的业务与UI状态
Stor的主要职责:
1 聚合actor
2 分派actor(单分派 事务分派)
3 通过bigQuery 计算咱们的查询语言(QL/PQL)
4 响应页面的事件(ViewAction)
5 注册响应 RL

import {Store,ViewAction} from 'plume2'import LoadingActor from 'loading-actor'import UserActor from 'user-actor'import TodoActor from 'todo-actor'// 响应页面事件的逻辑解决class AppViewAction extends ViewAction {    //show simple dispatch 显示简略分派    // when dispatch finished if status had changed,  如果状态已更改,则在调度实现时,    //each Relax component received message 每个组件都接管到音讯    update = () => {        //将计算的工作分派的到actor        //而后依据actor的返回值 重新聚合新的store的state        //该为单分派  当dispatch完结 store的state产生扭转的时候        //UI容器组件(StoreProvider,Relax) 会收到告诉从新re-render UI        this.store.dispatch('update')    }//  show multiple dispatch in a transaction  在事务中显示多个分派    save = () =>{        //事务分派        //很多场景下  计算应该是原子类型的  咱们想一想 dispatch 完结才告诉UI去re-render        //这个时候咱们就能够开启事务管制        // transaction  会返回值来判断在dispatch  过程中有没有产生谬误        // 如果产生谬误  数据会主动回滚到上一次的状态  防止脏数据        // 咱们也能够指定  自定义的回滚解决        // this.transaction(()=>{/*失常逻辑*/},()=>{/*自定义的回滚函数*/})        this.store.transaction(()=>{            this.store.dispatch('loading:end')            //这个中央能够失去上一次的dispatch之后的后果            //如:            const loading = this.state().get('loading')            this.store.dispatch('init:user',{id:1,name:'plume2'})            this.store.dispatch('save')        })    }}class AppStore extends Store{//   聚合Actor//   通过reduce各个actor的defaultState// 聚合出store的state作为source databindActor(){    //plume2  间接传递Actor的class    return [LoadingActor,UserActor,TodoActor]}bindViewAction(){    return{        AppViewAction    }}}

Store public-API

// 绑定须要聚合的ActorbindActor(): Array<Actor | typeof Actor>bindViewAction(): IViewActionMapper// 事务管制dispatch// dispatch: 失常逻辑// rollBack: 自定义回滚逻辑  默认是主动回滚到上一次的状态//返回是否产生回滚transaction(dispatch:Dispatch,rollBack:RollBack):boolean;// 计算QLbigQuery(ql:QueryLang):any// 以后store聚合的状态state():IMap;// 定义store状态更新告诉subscribe(cb:Handler):void;// 勾销订阅unsubscribe(cb:Handler):void;

StoreProvider

StoreProvider 容器组件连接咱们的React组件和AppStore。向React组件提供数据源

在StoreProvider中的次要工作是:
1 初始化咱们的AppStore
2 将AppStore的对象绑定到React组件的上下文
3 Relay 就是通过上下文取的store对象
4 监听Store的state变动

情谊提醒:咱们还提供了 debug模式

开启debug 模式 咱们就能够对数据进行全链路跟踪

跟踪store的dispatch actor的解决 relax对QL的计算等

import React, { Component } from 'react'import {StoreProvider} from 'iflux2'import AppStore from './store'//enable debug@StoreProvider(AppStore,{debug:true})class ShoppingCart extends Component{    render(){        return(            <Scene>                <HeaderContainer/>                <ShoppingCart/>                <BottomToolBarContainer/>            </Scene>        )    }}

Relax

Relax是plume2中十分重要的容器组件 相似Spring容器的依赖注入一样
外围性能会依据子组件的relaxProps中申明的数据,
通过智能计算属性的值 而后作为this.props.relaxProps透传给子组件

以此来解决React的props层层透传的verbose的问题

计算的规定
1 store 的state的值,间接给出值 得 immutable的门路,如 count:'count',todoText:['todo',1,'text']
2 store 的method 间接和method同名就ok 如:destroy:noop, 咱们更心愿通过ActionCreator来独自解决UI的side effect
3 如果属性是'viewAction' 间接注入store 中绑定的ViewAction
4 如果属性是QL 注入QL 计算之后的后果 如果PQL会主动绑定store的上下文

@Relaxexport default class Footer extends React.Component{    static relaxProps = {        changeFilter:noop,        clearCompleted:noop,        count:countQL,        loadingPQL:loadingPQL,        filterStatus:'filterStataus',        viewAction:'viewAction'    }    render(){        const{            changeFilter,            clearCompleted,            count,            filterStataus,            viewAction        } = this.props.relaxProps    }    //...}

QL/PQL

为什么咱们须要一个QL
1 咱们把store state 看成source data,因为UI展现的数据,可能须要依据咱们的源数据进行组合
2 咱们须要UI的数据具备reactive的能力 当source data变动的时候 @Relax 会去从新计算咱们的QL
3 命令式的编程手动的准确的解决数据之间的依赖和更新 Reactive会主动解决数据的依赖 然而同一个QL 可能会被执行屡次 造成计算上的节约
不过不须要放心 QL反对cache 确保path对应的数据没有变动的时候 QL 不会反复计算

QL = Query Lang
自定义查问语法 数据的源头是store的state返回的数据

Syntax QL(displayName,[string|array|QL...RelaxContainer,fn])

displayName,次要是帮忙咱们在debug状态更好的日志跟踪

string array QL:string array 都是immutable的get的path,QL其余的QL(反对无线嵌套)

fn:可计算状态的回调函数 bigQuery会获得所有的所有的数组中的path对应的值 作为参数传递给fn

// 返回:{//     id:1,//     name:'iflux2',//     address:{//         city:'南京'//     }// }store.state()//QL计算的后果值是'iflux2南京'const helloQL = QL('helloQL',[    'name',    ['address','city'],    (name,city)=>`${name}${city}`])Store.bigQuery(helloQL)