Emberjs——API/类/Ember.StateManager

Ember.StateManager Class

Emberjs API:http://emberjs.com/api/

继承自:Ember.State

定义于:packages/ember-states/lib/state_manager.js:170

所属模块:ember-states

说明:StateManager是Ember实现有限状态机的一部分。一个StateManager实例管理一些由Ember.State类实例化的属性(即状态),跟踪当前处于活动的状态,并在状态改变时触发回调函数。

 

定义状态

StateManager下的状态声明有两种方式。第一,定义states属性,该属性包含所有的状态:

managerA = Ember.StateManager.create({
  states: {
    stateOne: Ember.State.create(),
    stateTwo: Ember.State.create()
  }
})
managerA.get('states')
// {
//   stateOne: Ember.State.create(),
//   stateTwo: Ember.State.create()
// }

第二,直接添加Ember.State实例(或子类)作为StateManager的属性,这些状态会被收集到states属性里:

managerA = Ember.StateManager.create({
  stateOne: Ember.State.create(),
  stateTwo: Ember.State.create()
})
managerA.get('states')
// {
//   stateOne: Ember.State.create(),
//   stateTwo: Ember.State.create()
// }

 

初始状态

创建StateManager实例后会立即进入start属性定义的状态,或initialState属性里引用的状态名:

managerA = Ember.StateManager.create({
  start: Ember.State.create({})
})
managerA.get('currentState.name') // 'start'
managerB = Ember.StateManager.create({
  initialState: 'beginHere',
  beginHere: Ember.State.create({})
})
managerB.get('currentState.name') // 'beginHere'

由于initialState是一个属性,你还可以提供一个计算函数来引导初始状态:

managerC = Ember.StateManager.create({
  initialState: function(){
    if (someLogic) {
      return 'active';
    } else {
      return 'passive';
    }
  }.property(),
  active: Ember.State.create({}),
  passive: Ember.State.create({})
})

 

转移状态

StateManager可以拥有任意数量的Ember.State对象作为属性,但其中只能有一个是当前活动状态。

调用transitionTo方法在各状态间过渡:

robotManager = Ember.StateManager.create({
  initialState: 'poweredDown',
  poweredDown: Ember.State.create({}),
  poweredUp: Ember.State.create({})
})
robotManager.get('currentState.name') // 'poweredDown'
robotManager.transitionTo('poweredUp')
robotManager.get('currentState.name') // 'poweredUp'

在过渡到新状态之前,当前状态会调用exit方法,第一个参数时StateManager实例,第二个参数是一个表示过渡的对象。

在过渡到一个新状态后,新的当前状态会调用enter方法,参数同上。

robotManager = Ember.StateManager.create({
  initialState: 'poweredDown',
  poweredDown: Ember.State.create({
    exit: function(stateManager){
      console.log("exiting the poweredDown state")
    }
  }),
  poweredUp: Ember.State.create({
    enter: function(stateManager){
      console.log("entering the poweredUp state. Destroy all humans.")
    }
  })
})
robotManager.get('currentState.name') // 'poweredDown'
robotManager.transitionTo('poweredUp')
// will log
// 'exiting the poweredDown state'
// 'entering the poweredUp state. Destroy all humans.'

试图进入当前活动状态并不会再次触发enter或exit方法。试图过渡到一个不存在的状态不会引起任何改变。

robotManager = Ember.StateManager.create({
  initialState: 'poweredDown',
  poweredDown: Ember.State.create({
    exit: function(stateManager){
      console.log("exiting the poweredDown state")
    }
  }),
  poweredUp: Ember.State.create({
    enter: function(stateManager){
      console.log("entering the poweredUp state. Destroy all humans.")
    }
  })
})
robotManager.get('currentState.name') // 'poweredDown'
robotManager.transitionTo('poweredUp')
// will log
// 'exiting the poweredDown state'
// 'entering the poweredUp state. Destroy all humans.'
robotManager.transitionTo('poweredUp') // no logging, no state change
robotManager.transitionTo('someUnknownState') // silently fails
robotManager.get('currentState.name') // 'poweredUp'

每一个状态还可以有子状态作为它的属性。StateManager可以通过调用一系列transitionTo方法或通过传入完整路径给transitionTo方法,来过渡到指定的子状态。StateManager会保持跟踪当前状态的完整路径。

robotManager = Ember.StateManager.create({
  initialState: 'poweredDown',
  poweredDown: Ember.State.create({
    charging: Ember.State.create(),
    charged: Ember.State.create()
  }),
  poweredUp: Ember.State.create({
    mobile: Ember.State.create(),
    stationary: Ember.State.create()
  })
})
robotManager.get('currentState.name') // 'poweredDown'
robotManager.transitionTo('poweredUp')
robotManager.get('currentState.name') // 'poweredUp'
robotManager.transitionTo('mobile')
robotManager.get('currentState.name') // 'mobile'
// transition via a state path
robotManager.transitionTo('poweredDown.charging')
robotManager.get('currentState.name') // 'charging'
robotManager.get('currentState.path') // 'poweredDown.charging'

在状态间过渡时,会按层次触发每个状态及其嵌套的子状态的enter方法,以及exit方法,但顺序相反。

robotManager = Ember.StateManager.create({
  initialState: 'poweredDown',
  poweredDown: Ember.State.create({
    enter: function(){},
    exit: function(){
      console.log("exited poweredDown state")
    },
    charging: Ember.State.create({
      enter: function(){},
      exit: function(){}
    }),
    charged: Ember.State.create({
      enter: function(){
        console.log("entered charged state")
      },
      exit: function(){
        console.log("exited charged state")
      }
    })
  }),
  poweredUp: Ember.State.create({
    enter: function(){
      console.log("entered poweredUp state")
    },
    exit: function(){},
    mobile: Ember.State.create({
      enter: function(){
        console.log("entered mobile state")
      },
      exit: function(){}
    }),
    stationary: Ember.State.create({
      enter: function(){},
      exit: function(){}
    })
  })
})
robotManager.get('currentState.path') // 'poweredDown'
robotManager.transitionTo('charged')
// logs 'entered charged state'
// but does *not* log  'exited poweredDown state'
robotManager.get('currentState.name') // 'charged
robotManager.transitionTo('poweredUp.mobile')
// logs
// 'exited charged state'
// 'exited poweredDown state'
// 'entered poweredUp state'
// 'entered mobile state'

在开发期间,可以通过设置StateManager的enableLogging属性为true来显示状态过渡的信息,这些信息会在控制台输出。

robotManager = Ember.StateManager.create({
  enableLogging: true
})

 

使用动作管理当前状态

对给定状态,控制状态间的过渡是可能的,StateManager可以通过send方法接收和路由动作信息。传递一个动作名称作为参数来调用send方法,将开始搜索该动作名称定义的方法,搜索从当前状态开始,然后按嵌套层次向上移动到父状态,直到找到对应的方法,或到达StateManager自身。

如果指定动作名称被找到,它将会被调用,当前的StateManager将作为第一个参数被传递,第二个参数context对象作为可选项被传递。

managerA = Ember.StateManager.create({
  initialState: 'stateOne.substateOne.subsubstateOne',
  stateOne: Ember.State.create({
    substateOne: Ember.State.create({
      anAction: function(manager, context){
        console.log("an action was called")
      },
      subsubstateOne: Ember.State.create({})
    })
  })
})
managerA.get('currentState.name') // 'subsubstateOne'
managerA.send('anAction')
// 'stateOne.substateOne.subsubstateOne' has no anAction method
// so the 'anAction' method of 'stateOne.substateOne' is called
// and logs "an action was called"
// with managerA as the first argument
// and no second argument
someObject = {}
managerA.send('anAction', someObject)
// the 'anAction' method of 'stateOne.substateOne' is called again
// with managerA as the first argument and
// someObject as the second argument.

如果指定动作名称未找到,会抛出一个异常(Ember.Error)。检索只在当前状态的层次中进行,不会搜索其他分支部分的状态。

managerB = Ember.StateManager.create({
  initialState: 'stateOne.substateOne.subsubstateOne',
  stateOne: Ember.State.create({
    substateOne: Ember.State.create({
      subsubstateOne: Ember.State.create({})
    })
  }),
  stateTwo: Ember.State.create({
   anAction: function(manager, context){
     // will not be called below because it is
     // not a parent of the current state
   }
  })
})
managerB.get('currentState.name') // 'subsubstateOne'
managerB.send('anAction')
// Error: <Ember.StateManager:ember132> could not
// respond to event anAction in state stateOne.substateOne.subsubstateOne.

在动作方法里,给定的状态应当委托StateManager调用transitionTo方法。[StateManager作为第一个参数被传递给动作函数,用于调用transitionTo方法]

robotManager = Ember.StateManager.create({
  initialState: 'poweredDown.charging',
  poweredDown: Ember.State.create({
    charging: Ember.State.create({
      chargeComplete: function(manager, context){
        manager.transitionTo('charged')
      }
    }),
    charged: Ember.State.create({
      boot: function(manager, context){
        manager.transitionTo('poweredUp')
      }
    })
  }),
  poweredUp: Ember.State.create({
    beginExtermination: function(manager, context){
      manager.transitionTo('rampaging')
    },
    rampaging: Ember.State.create()
  })
})
robotManager.get('currentState.name') // 'charging'
robotManager.send('boot') // throws error, no boot action
                          // in current hierarchy
robotManager.get('currentState.name') // remains 'charging'
robotManager.send('beginExtermination') // throws error, no beginExtermination
                                        // action in current hierarchy
robotManager.get('currentState.name') // remains 'charging'
robotManager.send('chargeComplete')
robotManager.get('currentState.name') // 'charged'
robotManager.send('boot')
robotManager.get('currentState.name') // 'poweredUp'
robotManager.send('beginExtermination', allHumans)
robotManager.get('currentState.name') // 'rampaging'

过渡动作方法也可以通过Ember.State类的transitionTo方法来创建。下面两个例子是等价的:

aManager = Ember.StateManager.create({
  stateOne: Ember.State.create({
    changeToStateTwo: Ember.State.transitionTo('stateTwo')
  }),
  stateTwo: Ember.State.create({})
})
bManager = Ember.StateManager.create({
  stateOne: Ember.State.create({
    changeToStateTwo: function(manager, context){
      manager.transitionTo('stateTwo', context)
    }
  }),
  stateTwo: Ember.State.create({})
})

 

继承的方法

-参阅Ember.State

 

自有的方法

-getStateByPath(root, path)

参数:
@root--Ember.State,搜索的起点
@path--字符串,搜索的路径

返回:Ember.State,路径终点的状态

说明:通过路径查询状态。例子:

manager = Ember.StateManager.create({
  root: Ember.State.create({
    dashboard: Ember.State.create()
  })
});
manager.getStateByPath(manager, "root.dashboard")
// returns the dashboard state

 

-getStatesInPath(root, path)

参数:同getStateByPath

返回:一组从root参数开始的所有子状态。

说明:状态存储了它的子状态在它的states属性的哈希值里。传递posts.show将会查询root.states.posts.states.show。

 

继承的属性

-参阅Ember.State

 

自有的属性

-currentPath

说明:返回当前状态的路径,字符串。

 

-currentState

说明:返回当前的状态。不可直接设置,使用transitionTo方法来改变。

 

-errorOnUnhandledEvents

默认值:true

说明:如果设为true,在发送一个不能被检索到的事件时会引发一个异常。事件检索在当前状态及其父状态间进行。

 

-transitionEvent

默认值:'setup'

说明:当前stateManager发出的transitionEvent名字。

 

事件

-参阅Ember.State

posted @ 2012-11-15 20:19  Kiinlam  阅读(446)  评论(0)    收藏  举报