mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 12:29:55 +08:00
router updates
This commit is contained in:
173
ionic/routing/url-state.ts
Normal file
173
ionic/routing/url-state.ts
Normal file
@ -0,0 +1,173 @@
|
||||
import {IonicRouter} from './router';
|
||||
import * as util from '../util/util';
|
||||
|
||||
|
||||
class UrlStateManager {
|
||||
|
||||
constructor(window, router) {
|
||||
this.location = window.location;
|
||||
this.history = window.history;
|
||||
this.ls = window.localStorage;
|
||||
this.router = router;
|
||||
|
||||
// overkill for location change listeners, but ensures we
|
||||
// know when the location has changed. Only 1 of the listeners
|
||||
// will actually do the work, the other will be skipped.
|
||||
window.addEventListener('popstate', () => {
|
||||
this.onLocationChange();
|
||||
});
|
||||
window.addEventListener('hashchange', () => {
|
||||
this.onLocationChange();
|
||||
});
|
||||
}
|
||||
|
||||
load() {
|
||||
let paths = [this.getCurrentPath()];
|
||||
let savedPaths = this.paths();
|
||||
|
||||
if (savedPaths[savedPaths.length - 1] == paths[0]) {
|
||||
// the last path in the saved paths is the same as the
|
||||
// current path, so use the saved paths to rebuild the history
|
||||
paths = savedPaths;
|
||||
|
||||
} else {
|
||||
// the current path is not the same as the last path in the
|
||||
// saved history, so the saved history is no good, erase it
|
||||
this.paths([]);
|
||||
}
|
||||
|
||||
return Promise.resolve({
|
||||
paths: paths,
|
||||
priority: 0
|
||||
});
|
||||
}
|
||||
|
||||
stateChange(path, type, activeView) {
|
||||
let savedPaths = this.paths();
|
||||
|
||||
// check if the given path is different than the current location
|
||||
let isDifferentPath = (this.getCurrentPath() !== path);
|
||||
|
||||
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 (isDifferentPath) {
|
||||
this.history.back();
|
||||
}
|
||||
|
||||
if (savedPaths.length && savedPaths[savedPaths.length - 1] != path) {
|
||||
// only if the last item in the saved paths
|
||||
// equals this path then it can be removed
|
||||
savedPaths.pop();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (this._hasInit) {
|
||||
if (isDifferentPath) {
|
||||
// push the new state to the history stack since the path
|
||||
// isn't already in the location hash
|
||||
this.history.pushState(path, '', '#' + path);
|
||||
}
|
||||
|
||||
} else {
|
||||
// replace the very first load with the correct entering state info
|
||||
this.history.replaceState(path, '', '#' + path);
|
||||
this._hasInit = true;
|
||||
}
|
||||
|
||||
if (savedPaths[savedPaths.length - 1] != path) {
|
||||
// only if the last item in the saved paths does
|
||||
// not equal this path then it can be added
|
||||
savedPaths.push(path);
|
||||
|
||||
// don't allow the history to grow too large
|
||||
if (savedPaths.length > MAX_PATH_STORE) {
|
||||
savedPaths = savedPaths.slice( savedPaths.length - MAX_PATH_STORE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// save the new path data
|
||||
this.paths(savedPaths);
|
||||
|
||||
// ensure this resets
|
||||
this._currentPath = null;
|
||||
}
|
||||
|
||||
onLocationChange() {
|
||||
let currentPath = this.getCurrentPath();
|
||||
|
||||
if (currentPath == this._currentPath) {
|
||||
// absolutely no change since last onLocationChange
|
||||
return;
|
||||
}
|
||||
|
||||
// keep in-memory the current path to quickly tell if things have changed
|
||||
this._currentPath = currentPath;
|
||||
|
||||
// load up the saved paths
|
||||
let savedPaths = this.paths();
|
||||
|
||||
if (currentPath === savedPaths[savedPaths.length - 1]) {
|
||||
// do nothing if the last saved path is
|
||||
// the same as the current path
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentPath === savedPaths[savedPaths.length - 2]) {
|
||||
// the user is moving back
|
||||
this.router.pop();
|
||||
|
||||
} else {
|
||||
// the user is moving forward
|
||||
this.router.push(currentPath);
|
||||
}
|
||||
}
|
||||
|
||||
paths(val) {
|
||||
if (arguments.length) {
|
||||
// set in-memory data
|
||||
this._paths = val;
|
||||
|
||||
// set localStorage data
|
||||
try {
|
||||
this.ls.setItem(PATH_STORE_KEY, JSON.stringify(val));
|
||||
} catch(e) {}
|
||||
|
||||
} else {
|
||||
|
||||
if (!this._paths) {
|
||||
// we don't already have data in-memory
|
||||
|
||||
// see if we have data in localStorage
|
||||
try {
|
||||
let strData = this.ls.getItem(PATH_STORE_KEY);
|
||||
if (strData) {
|
||||
this._paths = JSON.parse(strData);
|
||||
}
|
||||
} catch(e) {}
|
||||
|
||||
// if not in localStorage yet then create new path data
|
||||
if (!this._paths) {
|
||||
this._paths = [];
|
||||
}
|
||||
}
|
||||
|
||||
// return the in-memory data
|
||||
return this._paths;
|
||||
}
|
||||
}
|
||||
|
||||
getCurrentPath() {
|
||||
// remove leading # to get the path
|
||||
return this.location.hash.slice(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const PATH_STORE_KEY = 'ionic:history';
|
||||
const MAX_PATH_STORE = 20;
|
||||
|
||||
IonicRouter.registerStateManager('url', UrlStateManager);
|
Reference in New Issue
Block a user