Эта статья также размещена в моем блоге,Добро пожаловать на просмотр 😄
написать впереди
В реальном сценарии использования веб-приложения есть некоторые интерактивные требования сценария, которые записывают состояние просмотра пользователем. Наиболее распространенным является возврат на страницу списка после входа на страницу сведений на странице списка, и пользователь хочет вернуться в состояние перед входом на страницу сведений, чтобы продолжить операцию. Однако в некоторых сценариях использования пользователи хотят иметь возможность получать последние данные, например, при переключении между страницами списка одноранговых узлов.
Таким образом, для двух описанных выше сценариев использования необходимо реализовать кэширование страниц по запросу. Поскольку логика маршрутизации приложения SPA также реализована во внешнем интерфейсе, логика маршрутизации может быть установлена во внешнем интерфейсе для достижения желаемого эффекта.
Использование технологий
- Vue.js как основные рамки
- Vue-router как интерфейсный менеджер маршрутов
- Vuex как инструмент управления состоянием
Главная идея
keep-alive определяет, читает ли текущий компонент кэшированный узел, который находится очень поздно во всем жизненном цикле, после afterEach, в основном до создания экземпляра компонента.(Поэтому можно обработать, читает ли текущий компонент кеш перед этим, я выбираю обрабатывать его в глобальном переднем щите)
Узел, который определяет, кэшируется ли текущий компонент, находится раньше, чем хук beforeRouteLeave компонента.
На основании вышеуказанной логики логика этого решения заключается в том, чтобы судить о открытой странице, динамически генерируют конфигурацию массива компонентов, которая требует Keepalive, кэшируйте те, которые могут быть в первую очередь кэшировать, а затем сделать суждение каждый раз, когда маршрут Переключается., Что читает кэш страницы по требованию.
- Используйте kepp-alive для кэширования и используйте атрибут include для настройки страниц, которые необходимо кэшировать.
- Поскольку конфигурация страницы, которую необходимо кэшировать, генерируется динамически, для ее хранения используется vuex.
- Напишите две конфигурации в метаинформации маршрутизации: одна — нужно ли кэшировать маршрут, а другая — конкретный массив маршрутов, который кэшируется только при входе с соответствующего маршрута.
- Установите в beforeEach, прежде чем вводить маршрут каждый раз, оценивайте входящий маршрут и все его родительские маршруты, если его необходимо кэшировать и попасть в определенный массив маршрутов, добавьте соответствующий маршрут в файл конфигурации кэша; если нет, добавьте соответствующий маршрут к файлу конфигурации кеша; Соответствующие маршруты удаляются. (Этот шаг реализует переключение маршрутов, чтение кэша при необходимости и повторную выборку данных, если они не нужны.)
- Используйте глобальный миксин, чтобы оценить текущий маршрут перед входом в соответствующий компонент, и добавьте маршрут в конфигурацию кэша, если его необходимо кэшировать. (Этот шаг реализует кэширование открытых в данный момент страниц, которые необходимо кэшировать.)
Реализация
1. Используйте атрибут включения для управления кэш маршрутом
Однако в среде vue-router нет локального регистрационного имени, и для компонента можно заполнить только атрибут имени.
Поэтому обязательно добавьте параметр name к компоненту, иначе анонимный компонент весь будет закеширован.
<keep-alive :include="$store.state.cachedRouteNames">
<router-view />
</keep-alive>
2. Добавьте глобальную конфигурацию кеша маршрутов
// store/index.js
const store = new vuex.Store({
state: {
// 缓存的路由列表
cachedRouteNames: [],
},
mutations: {
UPDATE_CACHEDROUTENAMES(state,{ action, route }) {
const methods = {
'add': () => {
state.cachedRouteNames.push(route)
},
'delete': () => {
state.cachedRouteNames.splice(state.cachedRouteNames.findIndex((e) => { return e === route}),1)
}
}
methods[action]()
}
}
})
3. Настройте метаданные маршрутизации и настройте маршруты, которые необходимо кэшировать.
keepAlive указывает, что маршрут нужно кэшировать, он должен, иначе он не будет кэшироваться
cacheWhenFromRoutes — необязательный массив,Если это ложное значение, он кэшируется в любое время; если это пустой массив, он не кэшируется в любое время
// router/index.js
{
path: '/productslist',
name: 'ProductsList',
component: ProductsList,
meta: {
keepAlive: true,
cacheWhenFromRoutes: ['ProductDetail'] // 此处配置的是路由的name
}
},
4. Настройте глобальную переднюю защиту и считывайте кэш по требованию.
// routeControl.js
// 需要缓存的路由名称数组
const cachedRouteNames = store.state.cachedRouteNames;
// 定义添加缓存组件name函数,设置的是组件的name
const addRoutes = (route) => {
const routeName = route.components.default.name
if (routeName && cachedRouteNames.indexOf(routeName) === -1) {
store.commit('UPDATE_CACHEDROUTENAMES', { action: 'add', route: routeName })
}
}
// 定义删除缓存组件name函数,设置的是组件的name
const deleteRoutes = (route) => {
const routeName = route.components.default.name
if (routeName && cachedRouteNames.indexOf(routeName) !== -1) {
store.commit('UPDATE_CACHEDROUTENAMES', { action: 'delete', route: routeName })
}
}
router.beforeEach((to, from, next) => {
// 处理缓存路由开始
// 在读取缓存之前,先对该组件是否读取缓存进行处理
to.matched.forEach((item, index) => {
const routes = item.meta.cacheWhenFromRoutes;
/**
* 此处有几种情况
* 1. 没有配置cacheWhenFromRoutes, 则一直缓存;
* 2. 配置了cacheWhenFromRoutes,但是首次打开此web app,则from.name为空,此时应该将该页面组件的name添加到缓存配置文件中
* 3. 配置了cacheWhenFromRoutes,from.name不为空,若命中cacheWhenFromRoutes,则添加该页面组件的name到缓存配置文件中,否则删除。
*
**/
if (item.meta.keepAlive && (!routes || (routes && (!from.name || routes.indexOf(from.name) !== -1)))) {
addRoutes(item)
} else {
deleteRoutes(item)
}
})
// 处理缓存路由结束
new Promise(( resolve, reject ) => {
// ..other codes
}).then( res => {
if ( res ) {
next(res)
} else {
next()
}
})
})
// 全局混入。此步骤的目的是在该组件被解析之后,若是属于需要缓存的组件,先将其添加到缓存配置中,进行缓存。
// 导航守卫的最后一个步骤就是调用 beforeRouteEnter 守卫中传给 next 的回调函数,此时整个组件已经被解析,DOM也已经更新。
Vue.mixin({
beforeRouteEnter(to, from, next) {
next(vm => {
to.matched.forEach((item) => {
const routeName = item.components.default.name
if (to.meta.keepAlive && routeName && cachedRouteNames.indexOf(routeName) === -1) {
store.commit('UPDATE_CACHEDROUTENAMES', { action: 'add', route: routeName })
}
})
})
},
})
напиши в конце
яма
- В этой схеме используются два имени, одно из которых заключается в использовании имени маршрута при задании конкретного маршрута. Во-вторых, когда файл конфигурации кэша создается динамически, используется имя компонента страницы.
- Не забудьте добавить в компонент атрибут name, чтобы облегчить использование атрибута include, а также облегчить отладку и отслеживание. Если у компонента отсутствует атрибут имени, по умолчанию будет использоваться кеш.
- При динамической обработке конфигурации кеша обязательно перейдите к .matched, иначе кеш родительского роута вложенного роута не сработает, а кеш дочернего роута тоже не сработает.
- Глобальное смешивание опасно, используйте его с осторожностью...
Вышеизложенное решение проверено на практике, я считаю, что есть более элегантное и эффективное решение. Если вам случится практиковать подобные методы, пожалуйста, поправьте меня, спасибо.