mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 03:32:21 +08:00
router updates
This commit is contained in:
@ -48,9 +48,9 @@ export class IonicApp {
|
|||||||
return this._zone;
|
return this._zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
stateChange(activeView, viewCtrl) {
|
stateChange(type, activeView) {
|
||||||
if (this._activeViewId !== activeView.id) {
|
if (this._activeViewId !== activeView.id) {
|
||||||
this.router.stateChange(activeView, viewCtrl);
|
this.router.stateChange(type, activeView);
|
||||||
this._activeViewId = activeView.id;
|
this._activeViewId = activeView.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ export class ViewController extends Ion {
|
|||||||
this.add(enteringItem);
|
this.add(enteringItem);
|
||||||
|
|
||||||
// notify app of the state change
|
// notify app of the state change
|
||||||
this.app.stateChange(enteringItem, this);
|
this.app.stateChange('push', enteringItem);
|
||||||
|
|
||||||
// start the transition
|
// start the transition
|
||||||
this.transition(enteringItem, leavingItem, opts, () => {
|
this.transition(enteringItem, leavingItem, opts, () => {
|
||||||
@ -115,7 +115,7 @@ export class ViewController extends Ion {
|
|||||||
let enteringItem = this.getPrevious(leavingItem);
|
let enteringItem = this.getPrevious(leavingItem);
|
||||||
if (enteringItem) {
|
if (enteringItem) {
|
||||||
// notify app of the state change
|
// notify app of the state change
|
||||||
this.app.stateChange(enteringItem, this);
|
this.app.stateChange('pop', enteringItem);
|
||||||
|
|
||||||
// start the transition
|
// start the transition
|
||||||
this.transition(enteringItem, leavingItem, opts, () => {
|
this.transition(enteringItem, leavingItem, opts, () => {
|
||||||
@ -299,7 +299,7 @@ export class ViewController extends Ion {
|
|||||||
leavingItem.didLeave();
|
leavingItem.didLeave();
|
||||||
|
|
||||||
// notify app of the state change
|
// notify app of the state change
|
||||||
this.app.stateChange(enteringItem, this);
|
this.app.stateChange('pop', enteringItem);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// cancelled the swipe back, return items to original state
|
// cancelled the swipe back, return items to original state
|
||||||
|
@ -38,41 +38,129 @@ export class IonicRouter {
|
|||||||
|
|
||||||
init(window) {
|
init(window) {
|
||||||
this.initHistory(window);
|
this.initHistory(window);
|
||||||
|
this.loadByPath(this.getCurrentPath(), this.otherwise());
|
||||||
let rootViewCtrl = this.activeViewController();
|
|
||||||
if (rootViewCtrl) {
|
|
||||||
let matchedRoute = this.match( this.getCurrentPath() ) || this.otherwise();
|
|
||||||
this.push(rootViewCtrl, matchedRoute);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initHistory(window) {
|
initHistory(window) {
|
||||||
this.location = window.location;
|
this.location = window.location;
|
||||||
this.history = window.history;
|
this.history = window.history;
|
||||||
|
|
||||||
window.addEventListener('popstate', (ev) => {
|
window.addEventListener('popstate', ev => {
|
||||||
this.onPopState(ev);
|
this.onPopState(ev);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onPopState(ev) {
|
loadByPath(path, fallbackRoute) {
|
||||||
let routeName = (ev.state && ev.state.name);
|
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();
|
let activeViewCtrl = this.activeViewController();
|
||||||
if (activeViewCtrl) {
|
if (activeViewCtrl) {
|
||||||
|
|
||||||
|
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();
|
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) {
|
pushState(route) {
|
||||||
let newPath = route.path;
|
let enteringState = {
|
||||||
if (this.location.hash !== '#' + newPath) {
|
path: route.path,
|
||||||
let state = {
|
backPath: this._lastPath,
|
||||||
name: route.name
|
forwardPath: null
|
||||||
};
|
};
|
||||||
this.history.pushState(state, '', '#' + newPath);
|
|
||||||
|
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) {
|
addViewController(viewCtrl) {
|
||||||
this._viewCtrls.push(viewCtrl);
|
this._viewCtrls.push(viewCtrl);
|
||||||
}
|
}
|
||||||
@ -147,7 +197,6 @@ export class IonicRouter {
|
|||||||
if (this._viewCtrls.length) {
|
if (this._viewCtrls.length) {
|
||||||
return this._viewCtrls[ this._viewCtrls.length - 1 ];
|
return this._viewCtrls[ this._viewCtrls.length - 1 ];
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentPath() {
|
getCurrentPath() {
|
||||||
@ -156,6 +205,10 @@ export class IonicRouter {
|
|||||||
return hash.slice(1);
|
return hash.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isNewPath(path) {
|
||||||
|
return (this.location.hash !== ('#' + path));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user