前端开发 Vue 状态优化

发布于:2025-07-27 ⋅ 阅读:(16) ⋅ 点赞:(0)

Vue 项目中的状态优化一般都会用Pinia替代Vuex,Pinia 是 Vue 生态系统中的一个轻量级状态管理库,作为 Vuex 的替代品,它提供了更简洁的 API 和更好的性能。

  • 模块化管理:使用 Pinia 时,建议将状态拆分为多个 store 模块,以避免单一状态树过于庞大和复杂。这不仅有助于维护,还能提升性能。

  • 懒加载 Store:通过 Pinia 的 defineStore 动态创建 store,当某个 store 仅在特定页面或组件中需要时,可以延迟加载它。这样可以减少应用的初始加载时间。

  • State 持久化:如果某些状态需要在页面刷新后保持,可以使用 Pinia 的插件功能将状态持久化到 localStorage 或 sessionStorage,避免不必要的网络请求或重新计算。

  • 避免不必要的深度响应:Pinia 允许你明确哪些状态需要响应式,哪些不需要。对于不需要响应式的复杂对象,可以使用 shallowRef 或 shallowReactive 来减少响应式开销。

1. 安装 Pinia 与配置

npm install pinia

设置 Pinia:

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)

// 创建 Pinia 实例
const pinia = createPinia()

app.use(pinia)
app.mount('#app')

 2. 创建模块化 Store

创建两个 Store 模块:userStore 和 productStore。其中 userStore 将使用状态持久化,productStore 将演示懒加载和避免不必要的深度响应。

stores/userStore.js:

// stores/userStore.js
import { defineStore } from 'pinia'
import { ref, computed, watch } from 'vue'

export const useUserStore = defineStore('user', () => {
  // 初始化状态,如果 localStorage 中有存储,优先使用存储的状态
  const name = ref(localStorage.getItem('user-name') || 'John Doe')
  const age = ref(parseInt(localStorage.getItem('user-age')) || 25)

  const doubleAge = computed(() => age.value * 2)

  // 监听状态变化,并将其保存到 LocalStorage
  watch(
    () => name.value,
    (newValue) => {
      localStorage.setItem('user-name', newValue)
    }
  )

  watch(
    () => age.value,
    (newValue) => {
      localStorage.setItem('user-age', newValue.toString())
    }
  )

  return {
    name,
    age,
    doubleAge,
  }
})

stores/productStore.js:

// stores/productStore.js
import { defineStore } from 'pinia'
import { shallowRef } from 'vue'

export const useProductStore = defineStore('product', () => {
  // 使用 shallowRef 来避免不必要的深度响应
  const products = shallowRef([])

  const addProduct = (product) => {
    products.value.push(product)
  }

  return {
    products,
    addProduct,
  }
})

3. 懒加载 Store

productStore 仅在需要时加载,例如在某个特定组件中。

components/ProductList.vue:

<template>
  <div>
    <h2>Product List</h2>
    <ul>
      <li v-for="product in products" :key="product.id">{{ product.name }}</li>
    </ul>
    <button @click="addNewProduct">Add Product</button>
  </div>
</template>

<script setup>
import { useProductStore } from '@ stores/productStore'
import { onMounted } from 'vue'

// 懒加载 productStore
const productStore = useProductStore()
const products = productStore.products

const addNewProduct = () => {
  productStore.addProduct({ id: Date.now(), name: `Product ${products.length + 1}` })
}

onMounted(() => {
  console.log('ProductList component mounted.')
})
</script>

4. 在其他组件中使用 userStore

components/UserProfile.vue:

<template>
  <div>
    <h2>User Profile</h2>
    <p>Name: {{ name }}</p>
    <p>Age: {{ age }}</p>
    <p>Double Age: {{ doubleAge }}</p>
  </div>
</template>

<script setup>
import { useUserStore } from '@/store/userStore'

// 使用 userStore,这个 Store 状态会被持久化
const userStore = useUserStore()

const { name, age, doubleAge } = userStore
</script>

5. 手动实现状态持久化

我们在 userStore 中通过 localStorage 手动实现了状态持久化。如果你需要更加通用的状态持久化插件,可以创建一个简单的 Pinia 插件。

plugins/persistedState.js:

// plugins/persistedState.js
export function createPersistedStatePlugin(options = {}) {
  return ({ store }) => {
    const { key = store.$id } = options

    // 从 LocalStorage 初始化状态
    const fromStorage = localStorage.getItem(key)
    if (fromStorage) {
      store.$patch(JSON.parse(fromStorage))
    }

    // 订阅状态变化,并将其保存到 LocalStorage
    store.$subscribe((mutation, state) => {
      localStorage.setItem(key, JSON.stringify(state))
    })
  }
}

注册插件

import { createPinia } from 'pinia'
import { createPersistedStatePlugin } from './plugins/persistedState'

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

const app = createApp(App)
app.use(pinia)
app.mount('#app')

网站公告

今日签到

点亮在社区的每一天
去签到