Skip to content

Keep-Alive

组件内部已针对keep-alive进行支持,内部代码:

js
onActivated(() => {
  scrollToOffset(reactiveData.offset);
});

示例

源码
vue
<template>
  <div class="main">
    <div class="demo-header">
      <p>演示虚拟列表与Vue keep-alive组件的结合使用,支持tab切换保留列表状态</p>
    </div>

    <!-- Tab切换 -->
    <div class="tab-container">
      <div class="tab-header">
        <button
          class="tab-btn"
          :class="{ active: activeTab === 'list1' }"
          @click="switchTab('list1')"
        >
          列表页面 1
        </button>
        <button
          class="tab-btn"
          :class="{ active: activeTab === 'list2' }"
          @click="switchTab('list2')"
        >
          列表页面 2
        </button>
      </div>

      <!-- Tab内容区域 -->
      <div class="tab-content">
        <keep-alive>
          <component
            :is="currentTabComponent"
            :key="activeTab"
            @update-status="updateStatus"
          />
        </keep-alive>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, markRaw } from 'vue';
import ListPage1 from './ListPage1.vue';
import ListPage2 from './ListPage2.vue';

const activeTab = ref<'list1' | 'list2'>('list1');
const list1Status = ref('未初始化');
const list2Status = ref('未初始化');

const currentTabComponent = computed(() => {
  return activeTab.value === 'list1' ? markRaw(ListPage1) : markRaw(ListPage2);
});

function switchTab(tab: 'list1' | 'list2') {
  activeTab.value = tab;
}

function updateStatus(tab: 'list1' | 'list2', status: string) {
  if (tab === 'list1') {
    list1Status.value = status;
  } else {
    list2Status.value = status;
  }
}
</script>

<style lang="scss" scoped>
.main {
  padding: 20px;
}

.demo-header {
  margin-bottom: 20px;

  h3 {
    margin: 0 0 10px 0;
    color: var(--vp-c-text-1);
  }

  p {
    margin: 0;
    color: var(--vp-c-text-2);
    font-size: 14px;
  }
}

.tab-container {
  margin-bottom: 20px;
}

.tab-header {
  display: flex;
  border-bottom: 2px solid var(--vp-c-border);
  margin-bottom: 20px;

  .tab-btn {
    padding: 12px 24px;
    border: none;
    background: transparent;
    color: var(--vp-c-text-2);
    cursor: pointer;
    font-size: 16px;
    font-weight: 500;
    border-bottom: 2px solid transparent;
    transition: all 0.3s ease;

    &:hover {
      color: var(--vp-c-text-1);
      background: var(--vp-c-bg-soft);
    }

    &.active {
      color: var(--vp-c-brand);
      border-bottom-color: var(--vp-c-brand);
      background: var(--vp-c-bg-soft);
    }
  }
}

.tab-content {
  height: 1000px;
  background: var(--vp-c-bg);
  border: 1px solid var(--vp-c-border);
  border-radius: 6px;
  overflow: hidden;
}

.status-info {
  margin-bottom: 20px;
  padding: 15px;
  background: var(--vp-c-bg-soft);
  border-radius: 6px;
  font-size: 14px;
  color: var(--vp-c-text-2);
}
</style>