mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-15 09:34:19 +08:00
This commit is contained in:
@ -22,7 +22,7 @@ class RouteManager extends React.Component<RouteComponentProps, RouteManagerStat
|
|||||||
listenUnregisterCallback: UnregisterCallback | undefined;
|
listenUnregisterCallback: UnregisterCallback | undefined;
|
||||||
activeIonPageId?: string;
|
activeIonPageId?: string;
|
||||||
currentDirection?: RouterDirection;
|
currentDirection?: RouterDirection;
|
||||||
locationHistory: LocationHistory = new LocationHistory();
|
locationHistory = new LocationHistory();
|
||||||
|
|
||||||
constructor(props: RouteComponentProps) {
|
constructor(props: RouteComponentProps) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -77,7 +77,13 @@ class RouteManager extends React.Component<RouteComponentProps, RouteManagerStat
|
|||||||
historyChange(location: HistoryLocation, action: HistoryAction) {
|
historyChange(location: HistoryLocation, action: HistoryAction) {
|
||||||
location.state = location.state || { direction: this.currentDirection };
|
location.state = location.state || { direction: this.currentDirection };
|
||||||
this.currentDirection = undefined;
|
this.currentDirection = undefined;
|
||||||
this.locationHistory.add(location);
|
if (action === 'PUSH') {
|
||||||
|
this.locationHistory.add(location);
|
||||||
|
} else if ((action === 'REPLACE' && location.state.direction === 'back') || action === 'POP') {
|
||||||
|
this.locationHistory.pop();
|
||||||
|
} else {
|
||||||
|
this.locationHistory.replace(location);
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
location,
|
location,
|
||||||
action
|
action
|
||||||
@ -111,21 +117,22 @@ class RouteManager extends React.Component<RouteComponentProps, RouteManagerStat
|
|||||||
* If the page is being pushed into the stack by another view,
|
* If the page is being pushed into the stack by another view,
|
||||||
* record the view that originally directed to the new view for back button purposes.
|
* record the view that originally directed to the new view for back button purposes.
|
||||||
*/
|
*/
|
||||||
enteringView.prevId = enteringView.prevId || leavingView.id;
|
enteringView.prevId = leavingView.id;
|
||||||
} else if (action === 'POP') {
|
} else if (action === 'POP') {
|
||||||
direction = leavingView.prevId === enteringView.id ? 'back' : 'none';
|
direction = leavingView.prevId === enteringView.id ? 'back' : 'none';
|
||||||
} else {
|
} else {
|
||||||
direction = direction || 'back';
|
direction = direction || 'back';
|
||||||
leavingView.mount = false;
|
leavingView.mount = false;
|
||||||
}
|
}
|
||||||
} else if (direction === 'back' || action === 'REPLACE') {
|
}
|
||||||
|
if (direction === 'back' || action === 'REPLACE') {
|
||||||
leavingView.mount = false;
|
leavingView.mount = false;
|
||||||
|
this.removeOrphanedViews(enteringView, enteringViewStack);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If there is not a leavingView, then we shouldn't provide a direction
|
// If there is not a leavingView, then we shouldn't provide a direction
|
||||||
direction = undefined;
|
direction = undefined;
|
||||||
}
|
}
|
||||||
this.removeOrphanedViews(enteringView, enteringViewStack);
|
|
||||||
} else {
|
} else {
|
||||||
enteringView.show = true;
|
enteringView.show = true;
|
||||||
enteringView.mount = true;
|
enteringView.mount = true;
|
||||||
@ -151,12 +158,13 @@ class RouteManager extends React.Component<RouteComponentProps, RouteManagerStat
|
|||||||
if (enteringEl) {
|
if (enteringEl) {
|
||||||
// Don't animate from an empty view
|
// Don't animate from an empty view
|
||||||
const navDirection = leavingEl && leavingEl.innerHTML === '' ? undefined : direction === 'none' ? undefined : direction;
|
const navDirection = leavingEl && leavingEl.innerHTML === '' ? undefined : direction === 'none' ? undefined : direction;
|
||||||
|
const shouldGoBack = !!enteringView.prevId || !!this.locationHistory.previous();
|
||||||
this.commitView(
|
this.commitView(
|
||||||
enteringEl!,
|
enteringEl!,
|
||||||
leavingEl!,
|
leavingEl!,
|
||||||
viewStack.routerOutlet,
|
viewStack.routerOutlet,
|
||||||
navDirection,
|
navDirection,
|
||||||
!!enteringView.prevId);
|
shouldGoBack);
|
||||||
} else if (leavingEl) {
|
} else if (leavingEl) {
|
||||||
leavingEl.classList.add('ion-page-hidden');
|
leavingEl.classList.add('ion-page-hidden');
|
||||||
leavingEl.setAttribute('aria-hidden', 'true');
|
leavingEl.setAttribute('aria-hidden', 'true');
|
||||||
@ -166,6 +174,8 @@ class RouteManager extends React.Component<RouteComponentProps, RouteManagerStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeOrphanedViews(view: ViewItem, viewStack: ViewStack) {
|
removeOrphanedViews(view: ViewItem, viewStack: ViewStack) {
|
||||||
|
// Note: This technique is a bit wonky for views that reference each other and get into a circular loop.
|
||||||
|
// It can still remove a view that probably shouldn't be.
|
||||||
const viewsToRemove = viewStack.views.filter(v => v.prevId === view.id);
|
const viewsToRemove = viewStack.views.filter(v => v.prevId === view.id);
|
||||||
viewsToRemove.forEach(v => {
|
viewsToRemove.forEach(v => {
|
||||||
// Don't remove if view is currently active
|
// Don't remove if view is currently active
|
||||||
@ -339,15 +349,20 @@ class RouteManager extends React.Component<RouteComponentProps, RouteManagerStat
|
|||||||
if (activeIonPage) {
|
if (activeIonPage) {
|
||||||
const { view: enteringView } = this.state.viewStacks.findViewInfoById(activeIonPage.prevId);
|
const { view: enteringView } = this.state.viewStacks.findViewInfoById(activeIonPage.prevId);
|
||||||
if (enteringView) {
|
if (enteringView) {
|
||||||
const lastLocation = this.locationHistory.findLastLocation(enteringView.routeData.match!.url);
|
const lastLocation = this.locationHistory.findLastLocationByUrl(enteringView.routeData.match!.url);
|
||||||
if (lastLocation) {
|
if (lastLocation) {
|
||||||
this.handleNavigate('replace', lastLocation.pathname + lastLocation.search, 'back');
|
this.handleNavigate('replace', lastLocation.pathname + lastLocation.search, 'back');
|
||||||
} else {
|
} else {
|
||||||
this.handleNavigate('replace', enteringView.routeData.match!.url, 'back');
|
this.handleNavigate('replace', enteringView.routeData.match!.url, 'back');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (defaultHref) {
|
const currentLocation = this.locationHistory.previous();
|
||||||
this.handleNavigate('replace', defaultHref, 'back');
|
if (currentLocation) {
|
||||||
|
this.handleNavigate('replace', currentLocation.pathname + currentLocation.search, 'back');
|
||||||
|
} else {
|
||||||
|
if (defaultHref) {
|
||||||
|
this.handleNavigate('replace', defaultHref, 'back');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -12,9 +12,30 @@ export class LocationHistory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
findLastLocation(url: string) {
|
pop() {
|
||||||
const reversedLocations = [...this.locationHistory].reverse();
|
this.locationHistory.pop();
|
||||||
const last = reversedLocations.find(x => x.pathname.toLowerCase() === url.toLowerCase());
|
}
|
||||||
return last;
|
|
||||||
|
replace(location: HistoryLocation) {
|
||||||
|
this.locationHistory.pop();
|
||||||
|
this.locationHistory.push(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
findLastLocationByUrl(url: string) {
|
||||||
|
for (let i = this.locationHistory.length - 1; i >= 0; i--) {
|
||||||
|
const location = this.locationHistory[i];
|
||||||
|
if (location.pathname.toLocaleLowerCase() === url.toLocaleLowerCase()) {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous() {
|
||||||
|
return this.locationHistory[this.locationHistory.length - 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
current() {
|
||||||
|
return this.locationHistory[this.locationHistory.length - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user