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