vue列表页面进入详情页面后返回白屏
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue列表页面进入详情页面后返回白屏相关的知识,希望对你有一定的参考价值。
参考技术A 我是一个程序员。第一次用,不知写些什么最近刚好碰到一个bug,就在这里记录下来吧(程序员的臭毛病就是写bug记录)。在ios上写的列表页面跳转到详情页面后点击返回键列表页面出现了部分白屏,然后下滑一下页面白屏就消失了,后来查了一下资料应该是跟ios浏览器滚动机制有关系然后影响了页面的渲染。记录下解决方法。
#app
position:relative;
在列表父级加一个定位就可以了
vue+vuerouter+vuex+keepalive动态缓存页面
需求:
vue+vuerouter+vuex
通过keepalive
控制页面缓存,有时候我们从列表页A
进入详情页
的时候,而详情页里面也有一个列表页B
,当我们从详情页进入列表页B
时,希望详情页缓存下来,当从列表页B
返回到详情页
时,我们需要详情页,不需要重新请求渲染页面,并且当前页面的滚动位置回到原来的位置,再继续返回到列表页A时,我们需要详情页不被缓存
目录结构
1project
2│
3└───src
4│ │
5| └───mixins
6| | scroll-position.js
7| |
8│ └───store
9| | | index.js
10| | |
11│ | └───common
12│ | index.js
13| |
14│ └───common
15│ | tools.js
16| |
17| └───router
18| | index.js
19| |
20| └───views
21| | list-a.vue
22| | detail.vue
23| | list-b.vue
24| |
25| └───App.vue
26
1.编写保存滚动位置方法
在目录下新建一个mixins
文件夹,在目录下新建一个scroll-position.js
,用户保存离开页面的滚动位置
1const scrollPosition = {
2 data() {
3 return {
4 }
5 },
6 activated() {
7 if (this.$route.meta.keepAlive) {
8 let pageName = this.$route.name;
9 let pagePositions = this.$store.state.CommonModule.pagePositions;
10 let res = pagePositions.find(v => v.name === pageName);
11 if (res && res.position > 0) {
12 this.$nextTick(function () {
13 document.documentElement.scrollTop = document.body.scrollTop = res.position || 0;
14 });
15 }
16 }
17 },
18 computed: {}
19};
20
21export default scrollPosition;
2.编写状态管理
在目录下新建一个store
文件夹,在store
文件夹下面新建一个index.js
,在store
文件夹下面新建一个common
文件夹,在common
文件夹下面新建一个index.js
/common/tools.js
1/**
2 * 获取数据类型,返回结果为 Number、String、Object、Array等
3 * @param value
4 * @returns {string}
5 */
6export const getRawType = (value) => {
7 return Object.prototype.toString.call(value).slice(8, -1)
8};
/store/common/tools.js
1import {getRawType} from '../../common/tools';
2
3const state = {
4 pagePositions: [],
5 cachedPages: []
6};
7
8const mutations = {
9 SAVE_POSITION(state, data) {
10 let pagePositions = state.pagePositions;
11 let key = -1;
12 pagePositions.find((v, k) => {
13 if (v.name === data.name) {
14 key = k;
15 return v
16 }
17 });
18 key >= 0 ? pagePositions[key] = data : pagePositions.push(data);
19 state.pagePositions = pagePositions;
20 },
21 SET_CACHED_PAGE(state, pageName) {
22 if (getRawType(pageName) === 'Array') {
23 state.cachedPages = pageName
24 } else {
25 let cached_pages = state.cachedPages;
26 let res = cached_pages.filter(cachedPage => cachedPage === `page-${pageName}`);
27 if (res.length <= 0) {
28 cached_pages.push(`page-${pageName}`);
29 state.cachedPages = cached_pages;
30 }
31 }
32 },
33 REMOVE_CACHED_PAGE(state, pageName) {
34 let cached_pages = state.cachedPages;
35 let index = cached_pages.findIndex(cachedPage => cachedPage === `page-${pageName}`)
36 if (index >= 0) {
37 cached_pages.splice(index, 1);
38 state.cachedPages = cached_pages
39 }
40 }
41};
42
43const getters = {
44};
45
46const actions = {
47 savePosition({commit}, data) {
48 commit('SAVE_POSITION', data)
49 },
50 setCachedPage({commit}, pageName) {
51 commit('SET_CACHED_PAGE', pageName)
52 },
53 removeCachedPage({commit}, pageName) {
54 commit('REMOVE_CACHED_PAGE', pageName)
55 }
56};
57
58export default {
59 namespace: true, //这里使用了vuex的命名空间,方便管理
60 state,
61 mutations,
62 getters,
63 actions
64}
/store/index.js
1import Vue from 'vue'
2import Vuex from 'vuex'
3import CommonModule from './common'
4
5Vue.use(Vuex);
6
7export default new Vuex.Store({
8 strict: process.env.NODE_ENV !== 'production', //严格模式
9 modules: {
10 CommonModule
11 }
12})
3.对特定页面编写缓存方法
app.vue
利用keeplive
的include
属性,详情可看https://cn.vuejs.org/v2/api/#keep-alive
1<template>
2 <div id="app">
3 <div class="app-container">
4 <keep-alive :include="cachedPages">
5 <router-view/>
6 </keep-alive>
7 </div>
8 </div>
9</template>
10
11<script type="text/ecmascript-6">
12 import {mapState} from 'vuex';
13
14 export default {
15 data() {
16 return {}
17 },
18 components: {
19 },
20 created() {
21 },
22 computed: {
23 ...mapState({
24 cachedPages: state => state.CommonModule.cachedPages
25 })
26 }
27 }
28</script>
29<style lang="less">
30</style>
/views/lista.vue
在详情页面
加入beforeRouteLeave
生命周期,
缓存的页面再次被激活的时候会触发activated
生命周期,页面被缓存离开的时候会触发deactivated
生命周期
/views/lista.vue
1<template>
2 <div>
3 i am list a
4 </div>
5</template>
6
7<script type="text/ecmascript-6">
8 import scrollPosition from "../mixins/scroll-position";
9
10 export default {
11 name: 'page-list-a',
12 mixins: [scrollPosition],
13 data() {
14 return {
15 }
16 },
17 beforeRouteLeave(to, from, next) {
18 if (['detail'].some(name => name === to.name)) {
19 from.meta.keepAlive = true;
20 this.$store.dispatch('setCachedPage', from.name).then(() => {
21 next()
22 });
23 } else {
24 from.meta.keepAlive = false;
25 this.$store.dispatch('removeCachedPage', from.name).then(() => {
26 next();
27 });
28 }
29 }
30 };
31</script>
32<style lang="less" scoped>
33</style>
/views/detail.vue
1<template>
2 <div>
3 i am detail
4 </div>
5</template>
6
7<script type="text/ecmascript-6">
8 export default {
9 name: 'page-detail',
10 data() {
11 return {
12 }
13 },
14 beforeRouteLeave(to, from, next) {
15 if (['list-a'].some(name => name === to.name)) {
16 from.meta.keepAlive = true;
17 this.$store.dispatch('setCachedPage', from.name).then(() => {
18 next()
19 });
20 } else {
21 from.meta.keepAlive = false;
22 this.$store.dispatch('removeCachedPage', from.name).then(() => {
23 next();
24 });
25 }
26 }
27 };
28</script>
29<style lang="less" scoped>
30</style>
list-b.vue
1<template>
2 <div>
3 i am list b
4 </div>
5</template>
6
7<script type="text/ecmascript-6">
8
9 export default {
10 name: 'page-list-b',
11 data() {
12 }
13</script>
14<style lang="less" scoped>
15</style>
/router/index.js
1import Vue from 'vue'
2import VueRouter from 'vue-router'
3
4// 重写新版VueRouter的push和replace方法的异常捕捉
5const originalPush = VueRouter.prototype.push;
6VueRouter.prototype.push = function push(location, onResolve, onReject) {
7 if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject);
8 return originalPush.call(this, location).catch(err => err)
9};
10Vue.use(VueRouter);
11
12const routes = [
13 {
14 path: '/list-a',
15 name: 'list-a',
16 meta: {
17 title: '列表页A'
18 },
19 component: () => import ('../views/list-a')
20 },
21 {
22 path: '/detail',
23 name: 'detail',
24 meta: {
25 title: '详情页',
26 keepAlive: true
27 },
28 component: () => import ('../views/detail')
29 },
30 {
31 path: '/list-b',
32 name: 'list-b',
33 meta: {
34 title: '列表页B'
35 },
36 component: () => import ('../views/list-b')
37 }
38];
39
40const router = new VueRouter({
41 mode: 'history',
42 routes
43});
44
45export default router
以上是关于vue列表页面进入详情页面后返回白屏的主要内容,如果未能解决你的问题,请参考以下文章