<Page>
  <h1>名词解释</h1>
  <Noun name='监听器'>
    事件的监听 **函数**。实际上在 Roof 内部，监听器并不是一个函数，而是一个对象，这个对象包含了触发事件时要执行的函数。还包含了函数触发时机的控制信息。
  </Noun>

  <Noun name='流程控制信息'>
    如上所说，流程控制信息是监听器的一部分。在实际的项目中，某个事件可能有多个监听器，监听器的触发顺序是有一定逻辑的。那么就需要提供监听器的流程控制信息，来告诉Roof以何种顺序执行监听器。流程控制信息本质上只是几个参数，如`before`、`after`、`first`、`last`等等。
  </Noun>

  <h1>应用事件</h1>

  <p>Roof 的事件概念类似于 Flux 中的 Action。不过更简单易用。在 Roof 中，全局只有一个事件对象实例。任何视图组件都可以平等地获得这个实例，然后通过它来触发相应的事件。我们以 **创建一条TODO** 的操作为例。</p>

  <p>首先在输入框的组件的代码中:</p>

  <Code type='javascript'>{`
  var Todo = require("../../data/type/todo").Node
var Mixin = require("../../../../src/mixin/react")
var Util = Mixin.util

//获得全局唯一事件对象实例
var bus = require("../../events")


//newTodo 用来保存输入框中的值
var newTodo = new Todo()
var todoMixin = new Mixin({todo:newTodo},{cursors:{"todo":"todo"}})


var Index = React.createClass({
  mixins : [todoMixin],
  onKeyUp : function(e){
    var todo = this.cursors.todo
    if( e.keyCode === 13 ){

      //触发事件，得到一个 promise
      bus.fire("todo.create", todo ).then(function(){
        todo.set("content","")
      },function(res){
        alert("创建失败:"+res.data)
      })

    }
  },
  render() {
    var todo = this.cursors.todo

    return (
      <div>
        <input value={todo.get("content")} onChange={Util.handleFormChange.bind(this,todo,"content")} onKeyUp={this.onKeyUp}/>
        <div></div>
      </div>
    )
  }
})
  `}</Code>

  <p>Roof 的事件对象实例推荐叫做 `bus`，总线的意思。我们通过 `bus.fire` 这个方法来触发事件。它可以传任意的参数，监听此事件的函数会按同样顺序收到这个参数。监听事件的函数统一称为 **监听器**。</p>

  <p>然后我们在一个单独的文件中监听这个事件</p>

  <Code type='javascript'>{`
  //  /events/todo.js
// 获得全局共享的数据
var localTodos = require("../data").source.asCreatorTodos

module.exports = function(bus){
    bus.on("todo.create", function createTodo(todo){
        //往服务器端发送请求
        return todo.push()
    })

    bus.on("todo.create", function updateLocalTodos(todo){
        //插入新数据
        //注意，这里的 todo 和 input 组件中 todo 是同一个引用
        //所以我们通过 .toObject 方法来丢掉引用。
        localTodos.insert(todo.toObject())
    }
}

  `}</Code>

  <p>到这里，一个 **发送事件** -- **处理事件** -- **更新数据** 的回路就全部完成了。</p>

</Page>




