用pinia和<KeepAlive>时需要注意Cache被改写的问题

发布时间 2023-03-30 03:57:22作者: zjhgx

用了pinia做状态管理,如果代码写的不当,遇到 <KeepAlive>时容易造成Cache被改写的问题

  computed: {
    ...mapWritableState(useGoodsStore, {
      _listData: 'items',
      _isListEnd: 'isListEnd',
      _max: 'maxPage',
    }),

如果在template里直接把 _listData作为页面的data,例如下面的router component Index.vue 和父级MainLayout.vue

          <q-list separator dense class="bg-secondary" id="scroll-target-id">
            <div
              id="containerId"
              v-bind:key="item.id"
              v-for="item in _listData"
              class="bg-primary"
              v-bind:class="{ 'q-pb-sm': !isBigScreen }"
            >
          <router-view v-slot="{ Component }">
            <KeepAlive>
              <component
                :is="Component"
                :key="$route.fullPath"
                :sort="sortIndex"
                ref="goods-list"
              />
            </KeepAlive>
          </router-view>

router.js

    path: '/',
    component: () => import('layouts/MainLayout.vue'),
    children: [
      {
        path: '',
        meta: { isGoodsList: true },

        components: {
          default: () => import('pages/Index.vue'),
          // hot: () => import('components/HotList.vue'),
          hot: () => import('components/ResourceSideList.vue'),
        },
        props: {
          default: (route) => ({
            sort: route.query.sort,
          }),
          hot: false,
        },
      },
      {
        path: 'list/:page',
        meta: { isGoodsList: true },

        components: {
          default: () => import('pages/Index.vue'),
          // hot: () => import('components/HotList.vue'),
          hot: () => import('components/ResourceSideList.vue'),
        },
        props: {
          default: (route) => ({ query: route.query.q, sort: route.query.sort }),
          hot: false,
        },
      },
      {
        path: ':path',
        meta: { isGoodsList: true },

        components: {
          default: () => import('pages/Index.vue'),
          hot: () => import('components/ResourceSideList.vue'),
        },
        props: {
          default: (route) => ({
            query: route.query.q,
            page: route.query.page,
            sort: route.query.sort,
          }),
          hot: false,
        },
      },

因为很多router都指向了Index.vue, 当有router1变成router2,例如从 'list/:page' 跳转到 ':path', 本来'list/:page' 的_listData已经被Cache,但到了':path',_listData的数据被改写,导致Cache里的数据也被改了。

正确的做法是在data里定义listData,页面的数据使用listData,在created()的hook里 this.listData = this._listData

          <q-list separator dense class="bg-secondary" id="scroll-target-id">
            <div
              id="containerId"
              v-bind:key="item.id"
              v-for="item in listData"
              class="bg-primary"
              v-bind:class="{ 'q-pb-sm': !isBigScreen }"
            >
  data() {
    return {
      listData: [],
     max: 0,
      isListEnd: false,

    }

  computed: {
    ...mapWritableState(useGoodsStore, {
      _listData: 'items',
      _isListEnd: 'isListEnd',
      _max: 'maxPage',
    }),

  created() {
    console.log('Index created' + this.$route.fullPath);
    this.listData = this._listData;
    this.max = this._max;
    this.listEnd = this._listEnd;
  },