Problems with SPA applications
Let’s look at an example:
- Product listings are searched by brand
-
Click the details button to enter the product details page
-
Click the back button of the details page, and the search item disappears, redisplaying all products
In SPA applications we rarely open a new window, so there is a problem that the page returns with the same state as the previous page
Solution Keep-alive
Keep alive is introduced
Is an abstract component: it does not render a DOM element on its own, nor does it appear in the component’s parent chain.
When dynamic components are wrapped, inactive component instances are cached rather than destroyed.
Parameters received by keep-alive:
Include – a string or regular expression. Only components with matching names are cached.
Exclude – a string or regular expression. Any component with a matching name will not be cached.
Max – Numbers. Maximum number of component instances can be cached.
For more information about keep-alive, please refer to cn.vuejs.org/v2/api/#kee…
Keep alive – use
Common solutions on the network (problematic)
App.vue
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if=! ""$route.meta.keepAlive"></router-view>
Copy the code
keeplist.vue
beforeRouteLeave (to, from, next) {
from.meta.keepAlive = to.name === 'keepdetail'
next()
}
Copy the code
router.js
{
path: 'keeplist',
name: 'keeplist',
meta: {
keepAlive: true
},
component: () => import('./views/keeplist')}Copy the code
Question:
The first operation home–> keeplist–> keepDetail is ideal, but the second operation returns home–> keeplist–> KeepDetail –> keeplist, the cached data is still there. The following figure
Analysis:
The first time you enter the Keeplist page, the default is meta. KeepAlive = true
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
Copy the code
When keeplist returns to home, the to.name! KeepAlive = ‘keepdetail’, so meta. KeepAlive is set to false, and the next time you enter the Keeplist page, you go
<router-view v-if=! ""$route.meta.keepAlive"></router-view>
Copy the code
When keeplist jumps to keepdetail, meta. KeepAlive is set to true, and when keeplist is returned from keepdetail, it goes
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
Copy the code
This invokes the same cached page, so there is a problem with the second return
Use scheme (implementation Scheme) from keep-alive property value
Keep-alive contains two attributes: include and exclude
Include and exclude attributes allow components to cache conditionally. Both can be represented as comma-delimited strings, regular expressions, or an array.
The official sample
<! -- comma-separated string --> <keep-alive include="a,b">
<component :is="view"></component> </keep-alive> <! -- regular expression (using 'v-bind') --> <keep-alive :include="/a|b/">
<component :is="view"></component> </keep-alive> <! -- array (using 'v-bind') --> <keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
Copy the code
- Manage include and exclude in VUex
exportdefault new Vuex.Store({ state: { keepInclude: [], keepExclude: [] }, mutations: {[ADD_KEEP_INCLUDE] (state, payload) {// TODO add cache name state.keepinclude = state.keepinclude. filter(item => item! == payload) state.keepInclude.push(payload) console.log(state.keepInclude) }, [REMOVE_KEEP_INCLUDE] (state, KeepInclude = state.keepinclude. filter(item => item! == payload) }, [ADD_KEEP_EXCLUDE] (state, KeepExclude = state.keepexclude. Filter (item => item! == payload) state.keepExclude.push(payload) }, [REMOVE_KEEP_EXCLUDE] (state, KeepExclude = state.keepexclude. Filter (item => item! == payload) } } })Copy the code
- Define two methods for easy use in components
import store from '@/store'
const newCache = function (routerName) {
store.commit('ADD_KEEP_INCLUDE', routerName)
store.commit('REMOVE_KEEP_EXCLUDE', routerName)
}
const clearCache = function (routerName) {
store.commit('ADD_KEEP_EXCLUDE', routerName)
store.commit('REMOVE_KEEP_INCLUDE', routerName)
}
export {
clearCache, newCache
}
Copy the code
- Cooperate with beforeRouteEnter and beforeRouteLeave to achieve data caching
import { clearCache, newCache } from '@/common/index'
export default {
name: 'keepa',
beforeRouteEnter (to, from, next) {
newCache('keepa')
next()
},
beforeRouteLeave (to, from, next) {
if (to.name.indexOf('home') > -1) {
clearCache('keepa')
}
next()
}
}
Copy the code
- Add the keep-alive component outside the routing page
<keep-alive :include="keepInclude" :exclude="keepExclude">
<router-view :key="$route.fullPath"/>
</keep-alive>
Copy the code
Important Notes
- The component names in include and exclude are the value of name in the single-file component, not the router name
- It is recommended to use an array for include and exclude. If include and exclude are empty, they are cached by default. Components are incorrectly cached
- Exclude takes precedence over include. If a component exists in both include and exclude, it will not be cached