欢迎光临焦作中国转运服务网
详情描述

1. keep-alive 组件缓存

基本用法

<!-- App.vue -->
<template>
  <div id="app">
    <keep-alive :include="cachedComponents">
      <router-view />
    </keep-alive>
  </div>
</template>

<script>
export default {
  data() {
    return {
      cachedComponents: ['Home', 'UserList'] // 要缓存的组件名
    }
  }
}
</script>

结合路由的缓存策略

// router/index.js
const routes = [
  {
    path: '/home',
    name: 'Home',
    component: () => import('./views/Home.vue'),
    meta: {
      keepAlive: true  // 需要缓存
    }
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('./views/Login.vue'),
    meta: {
      keepAlive: false // 不需要缓存
    }
  }
]
<!-- App.vue -->
<template>
  <keep-alive>
    <router-view v-if="$route.meta.keepAlive" />
  </keep-alive>
  <router-view v-if="!$route.meta.keepAlive" />
</template>

keep-alive 生命周期钩子

<script>
export default {
  name: 'MyComponent',
  activated() {
    // 组件被激活时调用
    console.log('组件被激活,恢复状态')
  },
  deactivated() {
    // 组件被停用时调用
    console.log('组件被停用,保存状态')
  }
}
</script>

2. 状态管理 (Vuex/Pinia)

Vuex 持久化

// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const state = {
  user: null,
  settings: {}
}

const mutations = {
  SET_USER(state, user) {
    state.user = user
    // 保存到 localStorage
    if (user) {
      localStorage.setItem('user', JSON.stringify(user))
    } else {
      localStorage.removeItem('user')
    }
  },
  LOAD_PERSISTED_STATE(state) {
    // 加载持久化状态
    const user = localStorage.getItem('user')
    if (user) {
      state.user = JSON.parse(user)
    }
  }
}

export default new Vuex.Store({
  state,
  mutations,
  // 可选:使用插件自动持久化
  plugins: [
    store => {
      // 初始化时加载
      store.commit('LOAD_PERSISTED_STATE')

      // 监听变化并保存
      store.subscribe((mutation, state) => {
        if (mutation.type === 'SET_USER') {
          localStorage.setItem('user', JSON.stringify(state.user))
        }
      })
    }
  ]
})

Pinia 持久化

// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    lastVisited: null
  }),
  actions: {
    increment() {
      this.count++
      this.saveToStorage()
    },
    saveToStorage() {
      localStorage.setItem('counterStore', JSON.stringify(this.$state))
    },
    loadFromStorage() {
      const saved = localStorage.getItem('counterStore')
      if (saved) {
        this.$state = JSON.parse(saved)
      }
    }
  }
})

3. 浏览器存储 API

封装存储工具类

// utils/storage.js
class StorageHelper {
  constructor(namespace = 'app') {
    this.namespace = namespace
  }

  set(key, value) {
    const data = this.getAll()
    data[key] = value
    localStorage.setItem(this.namespace, JSON.stringify(data))
  }

  get(key, defaultValue = null) {
    const data = this.getAll()
    return data[key] || defaultValue
  }

  getAll() {
    const data = localStorage.getItem(this.namespace)
    return data ? JSON.parse(data) : {}
  }

  remove(key) {
    const data = this.getAll()
    delete data[key]
    localStorage.setItem(this.namespace, JSON.stringify(data))
  }

  clear() {
    localStorage.removeItem(this.namespace)
  }
}

// 使用示例
const pageStorage = new StorageHelper('pageState')

// 在组件中使用
export default {
  data() {
    return {
      formData: {}
    }
  },
  created() {
    // 加载保存的状态
    const saved = pageStorage.get(this.$route.path)
    if (saved) {
      this.formData = saved
    }
  },
  methods: {
    saveForm() {
      // 保存状态
      pageStorage.set(this.$route.path, this.formData)
    }
  },
  beforeRouteLeave(to, from, next) {
    // 离开页面时保存状态
    pageStorage.set(from.path, this.formData)
    next()
  }
}

4. 路由守卫 + 本地存储

// router/index.js
const router = new VueRouter({ ... })

// 页面状态管理器
const pageStateManager = {
  saveState(route, state) {
    const key = `page_state_${route.path}`
    localStorage.setItem(key, JSON.stringify(state))
  },

  loadState(route) {
    const key = `page_state_${route.path}`
    const saved = localStorage.getItem(key)
    return saved ? JSON.parse(saved) : null
  },

  clearState(route) {
    const key = `page_state_${route.path}`
    localStorage.removeItem(key)
  }
}

// 全局路由守卫
router.beforeEach((to, from, next) => {
  // 如果需要保存离开页面的状态
  if (from.matched.some(record => record.meta.saveState)) {
    const component = router.app.$children.find(
      child => child.$vnode && child.$vnode.tag.includes(from.name)
    )
    if (component && component.getPageState) {
      const state = component.getPageState()
      pageStateManager.saveState(from, state)
    }
  }

  // 如果需要恢复目标页面的状态
  if (to.matched.some(record => record.meta.restoreState)) {
    const savedState = pageStateManager.loadState(to)
    to.meta.savedState = savedState
  }

  next()
})

5. 组件状态保存的最佳实践

混合方案示例

<template>
  <div>
    <!-- 表单组件 -->
    <input v-model="formData.name" />
    <input v-model="formData.email" />
    <button @click="saveForm">保存</button>
  </div>
</template>

<script>
import { debounce } from 'lodash'

export default {
  name: 'MyFormPage',
  data() {
    return {
      formData: {
        name: '',
        email: ''
      },
      isDataLoaded: false
    }
  },

  created() {
    this.loadSavedData()
    // 防抖保存
    this.debouncedSave = debounce(this.autoSave, 1000)
  },

  activated() {
    // keep-alive 激活时调用
    if (!this.isDataLoaded) {
      this.loadSavedData()
    }
  },

  deactivated() {
    // keep-alive 停用时自动保存
    this.autoSave()
  },

  methods: {
    loadSavedData() {
      // 从多个源加载数据
      const savedData = 
        localStorage.getItem(`form_${this.$route.path}`) ||
        this.$store.getters.getPageState(this.$route.path)

      if (savedData) {
        this.formData = JSON.parse(savedData)
        this.isDataLoaded = true
      }
    },

    saveForm() {
      // 保存到本地存储
      localStorage.setItem(
        `form_${this.$route.path}`,
        JSON.stringify(this.formData)
      )
      // 保存到 Vuex
      this.$store.commit('SAVE_PAGE_STATE', {
        path: this.$route.path,
        data: this.formData
      })
    },

    autoSave() {
      if (this.formData.name || this.formData.email) {
        localStorage.setItem(
          `form_${this.$route.path}_autosave`,
          JSON.stringify(this.formData)
        )
      }
    }
  },

  watch: {
    formData: {
      deep: true,
      handler() {
        this.debouncedSave()
      }
    }
  }
}
</script>

6. 第三方库推荐

vuex-persistedstate

npm install vuex-persistedstate
import createPersistedState from 'vuex-persistedstate'

export default new Vuex.Store({
  // ...
  plugins: [
    createPersistedState({
      key: 'vuex',
      storage: window.localStorage,
      reducer: (state) => ({
        user: state.user,
        settings: state.settings
      })
    })
  ]
})

pinia-plugin-persistedstate

npm install pinia-plugin-persistedstate
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

// 在 store 中使用
export const useUserStore = defineStore('user', {
  state: () => ({
    user: null
  }),
  persist: {
    enabled: true,
    strategies: [
      {
        key: 'user',
        storage: localStorage
      }
    ]
  }
})

选择建议

页面级缓存:使用 keep-alive 用户数据持久化:使用 Vuex/Pinia + 本地存储 表单状态临时保存:使用路由守卫 + sessionStorage 复杂应用:混合使用多种方案 SEO敏感页面:避免使用 keep-alive,改用服务端存储

根据具体需求选择合适的方案或组合使用多种方案,可以实现更灵活的状态管理。

相关帖子
城乡居民养老保险的缴费档次,是否允许在参保期间进行变更和调整?
城乡居民养老保险的缴费档次,是否允许在参保期间进行变更和调整?
红旗6.0sp1 分辨率调整解决方案
红旗6.0sp1 分辨率调整解决方案
焦作网站维护#网站建设推广服务公司,专业开发团队
焦作网站维护#网站建设推广服务公司,专业开发团队
2026年入境游免签政策,对国内旅游相关行业和服务标准提出了哪些新要求?
2026年入境游免签政策,对国内旅游相关行业和服务标准提出了哪些新要求?
焦作长途救护车出租就近派车-跨省转院救护车租赁
焦作长途救护车出租就近派车-跨省转院救护车租赁
昌吉病人转运120救护车|全国服务,当地派车
昌吉病人转运120救护车|全国服务,当地派车
申请2026年育儿补贴需要准备哪些具体的家庭证明材料与证件?
申请2026年育儿补贴需要准备哪些具体的家庭证明材料与证件?
商丘php开源cms二次开发@crm系统开发,网站制作
商丘php开源cms二次开发@crm系统开发,网站制作
2026年,租赁市场的信息透明度和规范性预计会有哪些方面的提升?
2026年,租赁市场的信息透明度和规范性预计会有哪些方面的提升?
针对制造业技能短缺问题,个人、企业和教育机构可以分别承担什么角色?
针对制造业技能短缺问题,个人、企业和教育机构可以分别承担什么角色?
和田救护车长途转运|急救车出租护送
和田救护车长途转运|急救车出租护送
平顶山智能响应式网站建设#网站优化公司,优秀开发团队
平顶山智能响应式网站建设#网站优化公司,优秀开发团队
如何评估自己当前的数字素养水平,并找到下一步需要重点学习的方向?
如何评估自己当前的数字素养水平,并找到下一步需要重点学习的方向?
商洛120救护车出租就近派车-急救车长途转运
商洛120救护车出租就近派车-急救车长途转运
作为独立接单者,需要了解哪些必要的法律知识来防范工作中的合同与薪酬风险?
作为独立接单者,需要了解哪些必要的法律知识来防范工作中的合同与薪酬风险?
2026年的智能家居,将如何更自然地集成人脸与指纹识别技术?
2026年的智能家居,将如何更自然地集成人脸与指纹识别技术?
企业或商户如果拥有不良信用记录,会面临哪些具体的经营限制或后果?
企业或商户如果拥有不良信用记录,会面临哪些具体的经营限制或后果?
延安精准获客软件#商城网站建设推广,收费透明
延安精准获客软件#商城网站建设推广,收费透明
鞍山网站搭建@网站搜索引擎优化,高端网站开发设计
鞍山网站搭建@网站搜索引擎优化,高端网站开发设计
如果捡到他人的身份证,正确的处理方式是什么,应该如何归还?
如果捡到他人的身份证,正确的处理方式是什么,应该如何归还?