vue2 设置keepAlive之后怎么刷新页面数据

本文讨论了移动端A、B、C页面的路由设置,特别是B页面在未封装和已封装组件情况下,如何处理keepAlive属性下的刷新与数据管理。涉及组件间通信的provide/inject策略,以及开发中规划的重要性。
摘要由CSDN通过智能技术生成

场景:移动端有 A、B、C 三个页面,A、B 页面路由设置了keepAlive属性,有下面两个场景:

1、A 页面 --> B 页面,B 页面刷新。

2、C 页面 --> B页面,B 页面不刷新。

一、分为以下两个情况讨论:

情况一、B 页面的代码未做组件封装,B 页面的核心代码如下:

<template>
  <div class="demo" ref="pageWrapRef">
    <div v-for="item in arr" :key="item.id">{{ item.name }}</div>
  </div>
</template>

<script>
export default {
  name: 'demo',
  data() {
    return {
      name: 'zhangsan',
      id: '1',
      arr: [],
      pageSourceName: ''
    };
  },
  mounted() {
    for (let i = 0; i < 100; i++) {
      this.arr.push({
        id: i,
        name: `张三${i}`
      });
    }
  },
  beforeRouteEnter(to, from, next) {
    next((vm) => {
      vm.pageSourceName = from.name;
    });
  },
  activated() {
    if (this.pageSourceName == 'A') {
      // 处理刷新数据的逻辑
      this.resetParams();
      this.initData();
    } else {
      // 滚动到指定位置
      const scrollTop = sessionStorage.getItem('scrollTop');
      if (scrollTop) {
        this.$refs.pageWrapRef.scrollTop = scrollTop;
      }
    }
  },
  beforeRouteLeave(to, from, next) {
    if (to.name == 'A') {
      sessionStorage.removeItem('scrollTop');
    } else {
      sessionStorage.setItem('scrollTop', this.$refs.pageWrapRef.scrollTop);
    }
    next();
  },
  methods: {
    initData() {
      console.log('初始化页面的接口请求');
    },

    resetParams() {
      this.name = 'zhangsan';
      this.id = '1';
      console.log('由于页面数据缓存了 所以要把变量重置');
    }
  }
};
</script>

<style scoped>
.demo {
  padding: 0.16rem 0;
  height: calc(100vh - 0.8rem);
  overflow-y: scroll;
  background-color: #fff;
}
</style>

情况二、B 页面的代码做了组件封装,比如说将 B 页面中的模块拆分成更小的业务组件,每个业务组件单独处理业务逻辑。如下图:

当 B 页面嵌套好几层组件时,这时在处理刷新跨层组件的数据时,如果使用常规的传值,传方法,会有一定的难度。

经过对各种方案的实验,选择了这种方案,B 页面的顶层组件通过 provide 属性向外暴露数顶层组件的页面数据,页面内的业务子组件通过 inject 属性接收顶层组件的数据。

页面交互如下:

二、以下分为三个部分:页面路由配置、页面代码、组件代码,如下:

1、页面路由配置:

export default [
  {
    path: '/demo/demoA',
    name: 'demoA',
    meta: { keepAlive: true },
    component: () => import('@/page/demo/demoA')
  },
  {
    path: '/demo/demoB',
    name: 'demoB',
    meta: { keepAlive: true },
    component: () => import('@/page/demo/demoB')
  },
  {
    path: '/demo/demoC',
    name: 'demoC',
    component: () => import('@/page/demo/demoC')
  }
];

2、三个页面的代码:

A 页面:

<template>
  <div class="demo-a" ref="pageWrapRef">
    demoA 页面
    <div
      class="item"
      v-for="(item, index) in list"
      :key="index"
      @click="handleJump(item)"
      >{{ item.id }}--{{ item.name }}</div
    >
  </div>
</template>

<script>
export default {
  name: 'demoA',
  data() {
    return {
      list: []
    };
  },
  activated() {
    const scrollTop = sessionStorage.getItem('scrollTopDemoA');
    if (scrollTop) {
      this.$refs.pageWrapRef.scrollTop = scrollTop;
    }
  },
  beforeRouteLeave(to, from, next) {
    sessionStorage.setItem('scrollTopDemoA', this.$refs.pageWrapRef.scrollTop);
    next();
  },
  mounted() {
    for (let i = 0; i < 100; i++) {
      this.list.push({
        id: `${i}`,
        name: `demoA`
      });
    }
  },
  methods: {
    handleJump(item) {
      this.$router.push({
        path: '/demo/demoB',
        query: {
          id: item.id
        }
      });
    }
  }
};
</script>

<style scoped>
.demo-a {
  background-color: #fff;
  height: 100vh;
  overflow-y: scroll;
}

.item {
  height: 44px;
  line-height: 44px;
  border-bottom: 1px #eee solid;
  padding: 0 15px;
}

.item:nth-child(odd) {
  background-color: paleturquoise;
}
</style>

B 页面

<template>
  <div class="demo-a" ref="pageWrapRef">
    demoB 页面
    <demoGrandfather />
  </div>
</template>

<script>
import demoGrandfather from './demoGrandfather.vue';

export default {
  name: 'demoB',
  provide() {
    return {
      demoB: this
    };
  },
  components: { demoGrandfather },
  data() {
    return {
      needRefresh: false
    };
  },
  activated() {
    const scrollTop = sessionStorage.getItem('scrollTopDemoB');
    if (scrollTop) {
      this.$refs.pageWrapRef.scrollTop = scrollTop;
    }
  },
  beforeRouteEnter(to, from, next) {
    if (to.name == 'demoB' && from.name == 'demoA') {
      next((vm) => {
        vm.needRefresh = true;
      });
    } else {
      next((vm) => {
        vm.needRefresh = false;
      });
    }
    next();
  },
  beforeRouteLeave(to, from, next) {
    if (to.name == 'demoA') {
      sessionStorage.removeItem('scrollTopDemoB');
    } else {
      sessionStorage.setItem(
        'scrollTopDemoB',
        this.$refs.pageWrapRef.scrollTop
      );
    }
    next();
  },
  methods: {}
};
</script>

<style scoped>
.demo-a {
  background-color: #fff;
  height: 100vh;
  overflow-y: scroll;
}

.item {
  height: 44px;
  line-height: 44px;
  border-bottom: 1px #eee solid;
  padding: 0 15px;
}

.item:nth-child(odd) {
  background-color: paleturquoise;
}
</style>

C 页面

<template>
  <div class="demo-c">
    demoC 页面
  </div>
</template>

<script>
export default {
  name: 'demoC'
};
</script>

<style scoped>
.demo-c {
}
</style>

3、B 页面中使用到的三个组件

顶层组件,demoGrandfather.vue 

<template>
  <div class="demo-grandfather">
    grandfather page
    <DemoParent />
  </div>
</template>

<script>
import DemoParent from './demoParent.vue';

export default {
  name: 'demoGrandfather',
  components: { DemoParent },
  data() {
    return {
      name: 'zhangsan',
      pageSourceName: ''
    };
  }
};
</script>

<style scoped>
.demo {
  padding: 0.16rem 0;
  height: calc(100vh - 0.8rem);
  overflow-y: scroll;
  background-color: #fff;
}
</style>

中间组件,demoParent.vue

<template>
  <div class="demo-parent">
    parent page
    <DemoChildren />
  </div>
</template>

<script>
import DemoChildren from './demoChildren.vue';

export default {
  name: 'demoParent',
  components: { DemoChildren },
  data() {
    return {
      name: 'zhangsan',
      id: '1',
      arr: [],
      pageSourceName: ''
    };
  },
  mounted() {
    for (let i = 0; i < 100; i++) {
      this.arr.push({
        id: i,
        name: `张三${i}`
      });
    }
  },
  methods: {
    initData() {
      console.log('初始化页面的接口请求');
    },

    resetParams() {
      this.name = 'zhangsan';
      this.id = '1';
      console.log('由于页面数据缓存了 所以要把变量重置');
    }
  }
};
</script>

<style scoped>
.demo {
  padding: 0.16rem 0;
  height: calc(100vh - 0.8rem);
  overflow-y: scroll;
  background-color: #fff;
}
</style>

底层组件,demoChildren.vue

<template>
  <div class="demo-children">
    <!-- 隐藏域 -->
    <div style="display: none;">{{ refresh }}</div>

    <div
      class="item"
      v-for="(item, index) in list"
      :key="index"
      @click.stop="handleJump(item)"
    >
      {{ item.id }} ----- {{ item.name }}</div
    >
  </div>
</template>

<script>
export default {
  name: 'demoChildren',
  inject: ['demoB'],
  data() {
    return {
      list: [],
      id: '0',
      refreshExecuted: false // 是否已刷新,默认未刷新
    };
  },
  deactivated() {
    this.refreshExecuted = false; // 更新为未刷新状态
  },
  computed: {
    refresh() {
      if (this.demoB.needRefresh) {
        if (this.$route.name == 'demoB' && !this.refreshExecuted) {
          this.refreshExecuted = true;
          this.resetParams();
          this.initData();
        }
      }
      return this.demoB.needRefresh;
    }
  },
  methods: {
    initData() {
      console.log('初始化页面的接口请求');
      for (let i = 0; i < 100; i++) {
        this.list.push({
          id: `${i}`,
          name: `demoB`
        });
      }
    },

    resetParams() {
      console.log('由于页面数据缓存了 所以要把变量重置');
    },

    handleJump(item) {
      this.$router.push({
        path: '/demo/demoC',
        query: {
          id: item.id
        }
      });
    }
  }
};
</script>

<style scoped>
.demo-a {
  background-color: #fff;
  height: 100vh;
  overflow-y: scroll;
}

.item {
  height: 44px;
  line-height: 44px;
  border-bottom: 1px #eee solid;
  padding: 0 15px;
}

.item:nth-child(odd) {
  background-color: paleturquoise;
}
</style>

三、总结:

我们在接到一个需求时,往往只会针对当前的需求进行代码开发,很少有意识去进行开发前的规划工作,这就导致我们在前期开发的有多开心,后期在改动时就有多痛苦。而本次的分享也是基于最近工作中遇到的一个场景,这个问题的出现,让我逐渐意识到规划的重要性,规划就是凡事谋定而后动,前期规划的越多,后期在进行迭代时,限制条件就会越少。

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值