diff --git a/src/router/ViewManager.js b/src/router/ViewManager.js new file mode 100644 index 00000000..c61cbb4f --- /dev/null +++ b/src/router/ViewManager.js @@ -0,0 +1,38 @@ +export default class ViewManager { + constructor() { + // Initializes the ViewManager with a Map to store page instances + // and a counter to keep track of the current entry. + this.store = new Map() + this.counter = 0 + this.createEntry() + } + + createEntry() { + // Creates a new entry in the store by incrementing the counter + // and initializing the entry with a null value. + this.counter++ + this.store.set(this.counter, null) + } + + setView(obj) { + // Sets the view object for the current entry in the store + this.store.set(this.counter, obj) + } + + getView() { + // Retrieves the view object for the current entry in the store. + return this.store.get(this.counter) + } + + removeView() { + // Removes the current entry from the store by deleting the entry + // associated with the current counter and then decrements the counter. + this.store.delete(this.counter) + this.counter-- + } + + size() { + // Returns the current number of entries in the store + return this.counter + } +} diff --git a/src/router/router.js b/src/router/router.js index 087db599..24764a38 100644 --- a/src/router/router.js +++ b/src/router/router.js @@ -23,6 +23,7 @@ import { Log } from '../lib/log.js' import { stage } from '../launch.js' import Focus from '../focus.js' import Announcer from '../announcer/announcer.js' +import ViewManager from './ViewManager.js' export let currentRoute export const state = reactive({ @@ -176,10 +177,23 @@ export const navigate = async function () { if (typeof route.transition === 'function') { route.transition = route.transition(previousRoute, route) } + let viewManager = cacheMap.get(route.hash) + + if (navigatingBack === false && route.options && route.options.keepAlive === true) { + // If ViewManager exists for the route hash, add a new entry to it. + if (viewManager !== undefined) { + viewManager.createEntry() + } else { + // Create a ViewManager instance for the route hash if it doesn't exist in cacheMap. + viewManager = new ViewManager() + cacheMap.set(route.hash, viewManager) + } + } let holder let routeData - let { view, focus } = cacheMap.get(route.hash) || {} + let { view, focus } = + (navigatingBack === true && viewManager !== undefined && viewManager.getView()) || {} if (!view) { // create a holder element for the new view @@ -329,16 +343,21 @@ const removeView = async (route, view, transition) => { // cache the page when it's as 'keepAlive' instead of destroying if (navigatingBack === false && route.options && route.options.keepAlive === true) { - cacheMap.set(route.hash, { view: view, focus: previousFocus }) - } else if (navigatingBack === true) { - // remove the previous route from the cache when navigating back - // cacheMap.delete will not throw an error if the route is not in the cache - cacheMap.delete(route.hash) + cacheMap.get(route.hash).setView({ view: view, focus: previousFocus }) + } else if (navigatingBack === true && cacheMap.has(route.hash)) { + // Remove the previous route entry from the ViewManager when navigating back. + const manager = cacheMap.get(route.hash) + manager.removeView() + + // If the ViewManager has zero entries, remove the corresponding route hash from cacheMap. + if (manager.size() === 0) { + cacheMap.delete(route.hash) + } } /* Destroy the view in the following cases: * 1. Navigating forward, and the previous route is not configured with "keep alive" set to true. - * 2. Navigating back, and the previous route is configured with "keep alive" set to true. - * 3. Navigating back, and the previous route is not configured with "keep alive" set to true. + * 2. Navigating back, and the previous route is not configured with "keep alive" set to true. + * 3. Navigating back, and the previous route is configured with "keep alive" set to true */ if (route.options && (route.options.keepAlive !== true || navigatingBack === true)) { view.destroy()