Vue 状态管理:从Vuex到Pinia,Vue 3官方推荐的状态管理库深度解析

大家好,我是前端宝哥。

在编程界有句老话:“命名和缓存失效是世上两大难题。” 我得说,在现代Web应用的状态管理上,这难题得排第三!

今天,咱们来深挖一下Vue的状态管理之道,并介绍一个超直观的解决方案——Pinia。

Vue状态管理:那些坑和局限性

自Vue 2起,我们用data属性来定义组件的状态,就像这样:

<template>
  <div>{{ user.name }}</div>
</template>

<script>
export default {
  data() {
    return { user: { name: 'John', age: 25 } };
  }
};
</script>

这就是所谓的 选项 API,在Vue 3中依然可用。Vue 3还带来了 组合式 API,它用reactiveref等新招数来定义状态。用这新API,我们可以这样写组件脚本:

<script setup>
import { reactive } from 'vue'

const user = reactive({ name: 'John', age: 25 });
</script>

但如果要跨组件访问状态,比如在导航栏显示用户名,在个人资料页展示详细信息,这就尴尬了。通常,我们用props逐层传递,但层级一多,就得在每个组件里加props,不管用不用得上。这叫prop 穿透,真不推荐。

更新共享数据时,子组件不能直接改props,得发事件让父组件来更新,再传下去。这...感觉有点笨。

Vue 3的救星来了:组合式 API 让我们能在任何脚本里用refreactive,还能导出状态,整个应用都能用。

我们可以把这状态叫做存储 (store)。比如,创建个store/user.js

import { reactive } from 'vue'

const user = reactive({ name: 'John', age: 25 });

export { user };

然后在组件里这么用:

<script setup>
import { user } from './stores/user.js';
</script>

<template>
  <h1>Hello, {{ user.name }}! You are {{ user.age }} years old.</h1>
</template>

看,现在状态有单一来源,组件间还能共享。

但这种模式虽简单,却不适合服务器端渲染 (SSR),因为状态只创建一次,可能导致数据泄露。而且,随着应用变大,可能需要更强大的状态管理。

Pinia:现代Vue应用的存储解决方案

Pinia 不仅支持SSR,还有Vue Devtools集成、热更新、TypeScript友好等优点。

Pinia由Vue Router的开发者Eduardo打造,现已取代Vuex,成为Vue 3官方推荐的状态管理库。

安装和设置

安装Pinia就一行命令:

npm install pinia

然后创建Pinia实例,传给Vue应用:

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

const pinia = createPinia()

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

现在,创建和管理存储就这么简单。

创建存储

defineStore方法创建Pinia存储,第一参数是名,第二参数是配置。比如,我们改写下user存储:

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({ name: 'John', age: 25 }),

  getters: {
    canVote: (state) => state.age >= 18,
  },

  actions: {
    blowCandles() {
      this.age++;
    }
  }
});

这就是选项存储 (Option Stores)。

喜欢组合式 API?Pinia也支持。用设置存储 (Setup Stores),用refcomputed定义状态和计算属性,函数返回要公开的:

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useUserStore = defineStore('user', () => {
  const name = ref('John');
  const age = ref(25);

  const canVote = computed(() => age.value >= 18);

  const blowCandles = () => age.value++;

  return { name, age, canVote, blowCandles };
});

设置存储的好处包括定义观察器、使用其他组合函数、注入属性等。

使用存储

定义了Pinia存储后,就可以在组件或组合函数里导入使用了:

<script setup>
import useUserStore from './stores/user.js'

const user = useUserStore();
</script>

<template>
  <button @click="user.blowCandles">
    I am {{ user.name }} and it's my birthday!
  </button>
</template>

通过user对象访问状态和操作,简单直观。解构时,用storeToRefs保持反应性。

真实例子

实际应用中,我们不会用固定值初始化存储。来看个登录示例:

import { ofetch } from 'ofetch'
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', () => {
  const data = ref();
  const token = ref();

  const isLoggedIn = computed(() => Boolean(token.value));

  async function login({ email, password }) {
    const { data, token: tok } = await ofetch('https://example.com/login', {
      method: 'POST',
      body: { email, password }
    });

    data.value = data;
    token.value = tok;
  }

  // ... logout, other methods
});

存储是封装应用逻辑的好地方。比如,登录操作请求API,保存用户数据和令牌。

然后在组件里这么用:

<script setup>
import useUserStore from './stores/user.js'

const user = useUserStore();
// ... form, error, handleSubmit
</script>

<template>
  <!-- ... template code -->
</template>

Pinia不仅管理用户会话,还能跟踪其他数据,减少服务器请求,让应用更快。

Pinia也适用于Vue 2

Pinia完全兼容Vue 2,所以如果你的Vue 2应用用Vuex,迁移到Pinia是升级到Vue 3的好起点。

Pinia Vue Devtools 插件

如果你用Vue Devtools,Pinia会有个新标签让你浏览存储,检查状态,甚至导入导出JSON。

总结

状态管理可能看起来有点吓人,但一旦掌握了,就简单多了。Pinia帮你组织数据,轻松访问。开发体验棒,集成简单。想试试?去官网看看。


往期推荐

38个Vue、Nuxt 和 Vite 技巧、窍门和实践的合集

Vue 如何处理异步组件加载错误

Vue 3 将推出新特性,可以抛弃虚拟DOM了!

Vue 小技巧:何时使用可组合函数

怎么才能做出一个牛逼的Vue 组件库?

掌握插槽魔法,助你进阶 Vue 开发,赋予组件无限可能!

微软 Edge 推出 "WebUI 2.0":从 React 到 Web Components + HTML,速度提升了42%

我是前端宝哥,每日分享前端开发技术,关注下面二维码,围观我的朋友圈。

fe4904cb861de0d95c849b800e6b0243.png

备注【文章群】可以进文章分享群,

备注【技术群】可以进技术交流群,

备注【副业群】可以进程序员副业群。

关注下方公众号加星标,送我的电子书资料

  • 回复「小抄」,领取Vue、JavaScript 和 WebComponent 小抄 PDF

  • 回复「Vue脑图」获取 Vue 相关脑图

  • 回复「思维图」获取 JavaScript 相关思维图

  • 回复「简历」获取简历制作建议

  • 回复「简历模板」获取精选的简历模板

  • 回复「电子书」下载我整理的大量前端资源,含面试、Vue实战项目、CSS和JavaScript电子书等。

  • 回复「知识点」下载高清JavaScript知识点图谱

  • 回复「读书」下载成长的相关电子书

70a901bd42d40349a2a6cd0916cdbeee.png

觉得好看,请关注我,点“在看”ff91544ba26445ae43a46cc5b62f2b3c.gif

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值