mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
router updates
This commit is contained in:
@ -48,9 +48,9 @@ export class IonicApp {
|
||||
return this._zone;
|
||||
}
|
||||
|
||||
stateChange(activeView, viewCtrl) {
|
||||
stateChange(type, activeView) {
|
||||
if (this._activeViewId !== activeView.id) {
|
||||
this.router.stateChange(activeView, viewCtrl);
|
||||
this.router.stateChange(type, activeView);
|
||||
this._activeViewId = activeView.id;
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ export class ViewController extends Ion {
|
||||
this.add(enteringItem);
|
||||
|
||||
// notify app of the state change
|
||||
this.app.stateChange(enteringItem, this);
|
||||
this.app.stateChange('push', enteringItem);
|
||||
|
||||
// start the transition
|
||||
this.transition(enteringItem, leavingItem, opts, () => {
|
||||
@ -115,7 +115,7 @@ export class ViewController extends Ion {
|
||||
let enteringItem = this.getPrevious(leavingItem);
|
||||
if (enteringItem) {
|
||||
// notify app of the state change
|
||||
this.app.stateChange(enteringItem, this);
|
||||
this.app.stateChange('pop', enteringItem);
|
||||
|
||||
// start the transition
|
||||
this.transition(enteringItem, leavingItem, opts, () => {
|
||||
@ -299,7 +299,7 @@ export class ViewController extends Ion {
|
||||
leavingItem.didLeave();
|
||||
|
||||
// notify app of the state change
|
||||
this.app.stateChange(enteringItem, this);
|
||||
this.app.stateChange('pop', enteringItem);
|
||||
|
||||
} else {
|
||||
// cancelled the swipe back, return items to original state
|
||||
|
@ -38,41 +38,129 @@ export class IonicRouter {
|
||||
|
||||
init(window) {
|
||||
this.initHistory(window);
|
||||
|
||||
let rootViewCtrl = this.activeViewController();
|
||||
if (rootViewCtrl) {
|
||||
let matchedRoute = this.match( this.getCurrentPath() ) || this.otherwise();
|
||||
this.push(rootViewCtrl, matchedRoute);
|
||||
}
|
||||
this.loadByPath(this.getCurrentPath(), this.otherwise());
|
||||
}
|
||||
|
||||
initHistory(window) {
|
||||
this.location = window.location;
|
||||
this.history = window.history;
|
||||
|
||||
window.addEventListener('popstate', (ev) => {
|
||||
window.addEventListener('popstate', ev => {
|
||||
this.onPopState(ev);
|
||||
});
|
||||
}
|
||||
|
||||
onPopState(ev) {
|
||||
let routeName = (ev.state && ev.state.name);
|
||||
loadByPath(path, fallbackRoute) {
|
||||
let self = this;
|
||||
let activeViewCtrl = self.activeViewController();
|
||||
let matchedRoute = self.match(path) || fallbackRoute;
|
||||
|
||||
console.log('onPopState', routeName);
|
||||
function zoneLoad() {
|
||||
self._app.zone().run(() => {
|
||||
activeViewCtrl.push(matchedRoute.cls);
|
||||
self._lastPath = matchedRoute.path;
|
||||
});
|
||||
}
|
||||
|
||||
if (activeViewCtrl && matchedRoute) {
|
||||
|
||||
if (matchedRoute.cls) {
|
||||
zoneLoad();
|
||||
|
||||
} else if (matchedRoute.module) {
|
||||
System.import(matchedRoute.module).then(m => {
|
||||
if (m) {
|
||||
matchedRoute.cls = m[matchedRoute.name];
|
||||
zoneLoad();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPopState(ev) {
|
||||
let newState = ev.state || {};
|
||||
let newStatePath = newState.path;
|
||||
let newStateBackPath = newState.backPath;
|
||||
let newStateForwardPath = newState.forwardPath;
|
||||
let lastLoadedStatePath = this._lastPath;
|
||||
|
||||
if (newStatePath === lastLoadedStatePath) {
|
||||
// do nothing if the last path is the same
|
||||
// as the "new" current state
|
||||
return;
|
||||
}
|
||||
|
||||
let activeViewCtrl = this.activeViewController();
|
||||
if (activeViewCtrl) {
|
||||
activeViewCtrl.pop();
|
||||
|
||||
if (newStateForwardPath === lastLoadedStatePath) {
|
||||
// if the last loaded state path is the same as the new
|
||||
// state's forward path then the user is moving back
|
||||
activeViewCtrl.pop();
|
||||
|
||||
} else if (newStateBackPath === lastLoadedStatePath) {
|
||||
// if the last loaded state path is the new state's
|
||||
// back path, then the user is moving forward
|
||||
this.loadByPath(newStatePath);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
stateChange(type, activeView) {
|
||||
if (activeView && activeView.ComponentType) {
|
||||
|
||||
let routeConfig = activeView.ComponentType.route;
|
||||
if (routeConfig) {
|
||||
let matchedRoute = this.match(routeConfig.path);
|
||||
|
||||
if (matchedRoute) {
|
||||
|
||||
if (type == 'pop') {
|
||||
// if the popstate came from the browser's back button (and not Ionic)
|
||||
// then we shouldn't force another browser history.back()
|
||||
// only do a history.back() if the URL hasn't been updated yet
|
||||
if (this.isNewPath(matchedRoute.path)) {
|
||||
this.history.back();
|
||||
}
|
||||
|
||||
} else {
|
||||
this.pushState(matchedRoute);
|
||||
}
|
||||
|
||||
this._lastPath = matchedRoute.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pushState(route) {
|
||||
let newPath = route.path;
|
||||
if (this.location.hash !== '#' + newPath) {
|
||||
let state = {
|
||||
name: route.name
|
||||
};
|
||||
this.history.pushState(state, '', '#' + newPath);
|
||||
let enteringState = {
|
||||
path: route.path,
|
||||
backPath: this._lastPath,
|
||||
forwardPath: null
|
||||
};
|
||||
|
||||
if (this._hasInit) {
|
||||
// update the leaving state to know what it's forward state will be
|
||||
let leavingState = util.extend(this.history.state, {
|
||||
forwardPath: enteringState.path
|
||||
});
|
||||
if (leavingState.path !== enteringState.path) {
|
||||
this.history.replaceState(leavingState, '', '#' + leavingState.path);
|
||||
}
|
||||
|
||||
if (this.isNewPath(route.path)) {
|
||||
// push the new state to the history stack since the path
|
||||
// isn't already in the location hash
|
||||
this.history.pushState(enteringState, '', '#' + enteringState.path);
|
||||
}
|
||||
|
||||
} else {
|
||||
// replace the very first load with the correct entering state info
|
||||
this.history.replaceState(enteringState, '', '#' + enteringState.path);
|
||||
this._hasInit = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,44 +189,6 @@ export class IonicRouter {
|
||||
}
|
||||
}
|
||||
|
||||
push(viewCtrl, route) {
|
||||
let self = this;
|
||||
|
||||
function run() {
|
||||
self._app.zone().run(() => {
|
||||
viewCtrl.push(route.cls);
|
||||
});
|
||||
}
|
||||
|
||||
if (viewCtrl && route) {
|
||||
if (route.cls) {
|
||||
run();
|
||||
|
||||
} else if (route.module) {
|
||||
System.import(route.module).then(m => {
|
||||
if (m) {
|
||||
route.cls = m[route.name];
|
||||
run();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stateChange(activeView) {
|
||||
if (activeView && activeView.ComponentType) {
|
||||
|
||||
let routeConfig = activeView.ComponentType.route;
|
||||
if (routeConfig) {
|
||||
let matchedRoute = this.match(routeConfig.path);
|
||||
|
||||
if (matchedRoute) {
|
||||
this.pushState(matchedRoute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addViewController(viewCtrl) {
|
||||
this._viewCtrls.push(viewCtrl);
|
||||
}
|
||||
@ -147,7 +197,6 @@ export class IonicRouter {
|
||||
if (this._viewCtrls.length) {
|
||||
return this._viewCtrls[ this._viewCtrls.length - 1 ];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getCurrentPath() {
|
||||
@ -156,6 +205,10 @@ export class IonicRouter {
|
||||
return hash.slice(1);
|
||||
}
|
||||
|
||||
isNewPath(path) {
|
||||
return (this.location.hash !== ('#' + path));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user