# Roof 容器-Container

** 注意，使用 Roof.createRootContainer 和 Roof.createContainer 时仍然要 import React。这是 babel 编译 jsx 的需要。**

在首页示例中，我们通过 `Roof.createRootContainer` 和 `Roof.createContainer` 这两个 API 创建了 Roof 应用，实际上这已经是 Roof 全部需要掌握的 API。
下面我们再来详细讲解一下。

## Roof.createRootContainer

`Roof.createRootContainer` 是用来定义整个 Roof 应用的，它负责定义事件和数据。仍然以首页代码为例:

```javascript
import React from 'react';
import Roof from 'roof';
import _ from 'roof/addon/react/container';
import User from './User';
import UserDataFactory from '../data/user';
import UserListenerFactory from '../event/user';

const App = Roof.createRootContainer({
  //告诉 Roof 我们应用的数据如何构造
  data: {
    user: UserDataFactory
  },
  //告诉 Roof 我们应用的事件和监听器信息
  events: {
    user: UserListenerFactory
  },
  render(){
    return <div>
      <div>Hello :</div>
      <User />
    </div>
  }
})

export default App;
```

### 数据定义

数据部分定义是一个键值对，键表示数据的名称，在子组件里面订阅数据就是通过名称，在事件监听器里面获取数据也是通过这个名称，代码中的名称为 `user`。
数据定义的值是一个函数，这个函数负责生成相应的数据实例。我们先来看代码:

```javascript
import Roof from 'roof';

const User = Roof.Node.createClass({
  getFullName(){
    return this.get('name') + ' ' + this.get('family')
  }
})

export default function UserFactory(){
  return new User({
    name:'Jane',
    family : 'Smith',
    age : 17
  })
}
```

前面提到过，Roof 使用的是一种非常接近**传统面向对象**的概念来管理数据。`Roof.Node` 看做是 Roof 提供的基类。
`User` 则是用户自己继承出来的子类，在创建子类时还可以定义它独有的 API。更多关于类定义的信息请参考数据部分文档。
Roof 最后需要的就是一个函数，函数返回用户自己子类的实例。


很多时候，数据初始化的操作时异步的，


### 事件定义

事件定义也是一个键值对，键名是当前这一系列之间监听器的模块名，之后在事件的流程控制中会用到。而值也是一个函数，这个函数也返回一个键值对，
返回的键值对中键名就是 事件名，值是事件监听器。

```javascript

export default function manuplateUser(data) {

  return {
    'user.addAge': function ( ageToAdd ) {
      const user = data.get('user')
      const age = user.get('age')
      user.set('age', age + ageToAdd)
    }
  }
}

```

实例代码中监听了一个叫做 `user.addAge` 的事件，如果触发了该事件，那么后面的监听函数就会被执行，在监听函数中，我们可以通过 `data.get` 拿到自己想要数据。
拿数据使用的名称就是我们之前定义数据时提到的名称，这里是 `user`。

## Roof.createContainer

在 Root.createRootContainer 中定义的事件和数据，是在 `Roof.createContainer` 创建的容器中使用的。使用非常简单:

```javascript
import React from 'react';
import Roof from 'roof';

const User = Roof.createContainer({
  cursors : {
    MyUser : 'user'
  },
  addAge(){
    this.bus.fire('user.addAge', 2)
  },
  render(){
    return <div>
      <div>{this.props.MyUser.getFullName()}</div>
      <a onClick={this.addAge}>add age</a>
    </div>
  }
})

export default User;
```

我们通过 cursors 属性声明自己需要的数据，这里也是一个键值对，键名表示 “数据将通过props上的属性传递过来” ，值则是数据在 `Roof.createRootContainer` 中定义的名称。

触发事件也非常简单，通过 `this.bus.fire` 既可触发相应的事件。`this.fire` 参数第一个为事件名，之后可以无限传递参数， 监听器会依次收到。




