在公司的ionic项目中我们定义了如下状态:
$stateProvider
.state('A', {
abstract: true,
views: {
root: {
template: '<ion-nav-view id="ViewA"></ion-nav-view>'
}
}
})
.state('A.B', {
url: '/A/B',
templateUrl: 'A/B.tpl.html',
controller: 'ABCtrl'
})
.state('A.C', {
abstract: true,
url: '/A/C'
})
.state('A.C.D', {
url: '/D',
views: {
'root@': {
templateUrl: 'A/C/D.tpl.html',
controller: 'ACDCtrl'
}
}
})
.state('E', {
url: '/E',
views: {
root: {
templateUrl: 'E.tpl.html'
}
}
})
其中views里面的root是在index.html里定义的ion-nav-view:
<html>
...
<body ng-app="starter">
...
<ion-nav-view name="root"></ion-nav-view>
</body>
</html>
并且ABCtrl和ACDCtrl的代码中都注册监听了afterEnter事件。
按理说从状态A.B跳转到状态A.C.D时,ACDCtrl里的afterEnter会被执行,可实际运行的时候却没有。但是从E跳转到A.C.D则没有问题,ACDCtrl里的afterEnter会如期被调用。从E跳到A.B也没有问题,ABCtrl里的afterEnter也会执行。
公司项目的ionic lib版本是1.3.1:
$ ionic lib
Local Ionic version: 1.3.1 (/Users/zhixiangzhu/my-ionic-project/www/lib/ionic/version.json)
Latest Ionic version: 1.3.3 (released 2017-02-24)
* Local version is out of date
本文末尾附上了我自己写的一个ionic小项目专用于重现这个问题。该项目的ionic lib版本是1.3.3:
$ ionic lib
Local Ionic version: 1.3.3 (/Users/zhixiangzhu/ionic-afterEnter-test/www/lib/ionic/version.json)
Latest Ionic version: 1.3.3 (released 2017-02-24)
* Local version up to date
于是我钻进了ionic的代码里研究了一番。afterEnter是在ionicViewSwitcher的transitionComplete函数中,也就是在状态跳转完成时触发的:
function transitionComplete() {
...
// the most recent transition added has completed and all the active
// transition promises should be added to the services array of promises
if (transitionId === transitionCounter) {
...
// emit that the views have finished transitioning
// each parent nav-view will update which views are active and cached
switcher.emit('after', enteringData, leavingData); // ionic在这里触发afterEnter
...
}
...
}
可以看到afterEnter触发的条件是transitionId === transitionCounter。ACDCtrl的afterEnter没有被调用,正是因为这个条件没有被满足。
于是需要理解transitionId和transitionCounter分别是什么。两者的定义在如下代码中ÿ