10 月 23 - 25 日,QCon 上海站即将召开,现在购票,享9折优惠 了解详情
写点什么

预填充 Vue.js 全局存储状态的三种方法

  • 2020-12-25
  • 本文字数:2842 字

    阅读完需:约 9 分钟

预填充Vue.js全局存储状态的三种方法

本文最初发布于 austingil.com 网站,经原作者授权由 InfoQ 中文站翻译并分享。


在构建 Vue.js 应用程序时,当这些应用程序的规模扩张到一定程度后,你就可能会遇到管理全局状态的需求了。还好,他们的核心开发团队提供了 Vuex 这个便利的工具,这是 Vue.js 应用程序状态管理库的事实标准。


要入门这个库非常简单,所以我假设你已经熟悉了 Vuex 的实现。这篇文章并不是一篇入门教程。如果你需要从头开始了解的话,那么我建议你查阅文档


Vuex 让我们可以更方便地管理全局数据存储。对于下面的示例,假设我们有一个看起来像这样的存储:


import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)const store = new Vuex.Store({  state: {    user: null  },  mutations: {    setUser (state, user) {      state.user = user    }  },})
复制代码


这个存储的初始状态有一个空的 user 对象,以及一个可以更新状态的 setUser 突变。然后,在我们的应用程序中,我们可能想要显示 user 的详细信息:


<template>  <div>    <p v-if="user">Hi {{ user.name }}, welcome back!</p>    <p v-else>You should probably log in.</p>  </div></template><script>export default {  computed {    user() {      return this.$store.state.user    }  }}</script>
复制代码


这样一来,在应用加载时,如果用户已登录,则应用会向用户显示一条欢迎消息。否则,它将告诉用户他们需要登录。我知道这是一个简单的示例,不过你可能也遇到过类似的情况。你可能也会像我一样产生这样的疑问:


如何在我的应用加载之前将数据添加到存储中?


还好,我们倒是有一些方法可选。


设置初始状态


预填充全局存储的最笨方法是在创建存储时设置初始状态:


import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)const store = new Vuex.Store({  state: {    user: { name: "Austin" }  },  mutations: {    setUser (user) {      state.user = user    }  }})
复制代码


显然,这只有在你提前知道关于用户的详细信息时才能用。可是在构建应用程序时,我们可能不知道用户会起什么名字,但是还有另一种选择。


我们可以利用 localStorage 保留用户信息的一个副本。当他们登录时,你可以在 localStorage 中设置详细信息;而当他们登出时,你可以从 localStorage 中删除详细信息。


应用加载后,你可以将用户详细信息从 localStorage 拉到初始状态里面:


import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)const store = new Vuex.Store({  state: {    user: localStorage.get('user')  },  mutations: {    setUser (user) {      state.user = user    }  }})
复制代码


如果你使用的数据不需要严格的安全限制,那么这种方法的效果会很好。我建议使用 vuex-persistedstate 库来帮助自动化这里的操作。


请记住,切勿将诸如身份验证令牌之类的非常敏感的数据存储在 localStorage 中,因为 XSS 攻击可能会将其作为目标。因此,我们的示例适合存储用户名,但不适用于身份令牌。这些敏感数据应该只存储在内存中(仍然可以选择 Vuex,只是不能持久保存)。


在应用挂载时请求数据


现在,假设出于某种原因,我们不希望将数据存储在 localStorage 中。我们的下一个选项可能是将初始状态保留为空,然后允许我们的应用程序挂载。应用挂载完毕后,我们可以向服务器发出一些 HTTP 请求以获取数据,然后更新全局状态:


<template>  <div>    <p v-if="user">Hi {{ user.name }}, welcome back!</p>    <p v-else>You should probably log in.</p>  </div></template><script>export default {  computed {    user() {      return this.$store.state.user    }  },  async mounted() {    const user = await getUser() // Assume getUser returns a user object with a name property    this.$store.commit('setUser', user)  }}</script>
复制代码


这种办法效果很好,但是现在我们有了一种奇怪的用户体验。这个应用程序将加载并发送请求,但是当用户等待请求返回时,他们会看到“你可能应该登录”的提示。当请求返回时,假设他们已登录会话,该消息将迅速更改为“Hi{{user.name}},欢迎回来!”。这种跳跃看起来会很混乱。


为了解决这个问题,我们可以在请求结束时简单地显示一个加载中的元素:


<template>  <div>    <p v-if="loading">Loading...</p>    <p v-else-if="user">Hi {{ user.name }}, welcome back!</p>    <p v-else>You should probably log in.</p>  </div></template><script>export default {  data: () => ({    loading: false  }),  computed {    user() {      return this.$store.state.user    }  },  async mounted() {    this.loading = true    const user = await fetch('/user').then(r => r.json()) // Assume getUser returns a user object with a name property    this.$store.commit('setUser', user)    this.loading = false  }}</script>
复制代码


请记住,这是一个非常简单的示例。在你自己的项目里,你可能会有用于加载动画的专用组件,并且可能有一个<router-view>组件来代替此处的用户消息。你也可以选择通过一个 Vuex 动作来发出这个 HTTP 请求。不过基本概念都是一样的。


在应用加载之前请求数据


本文的最后一个示例是发出与上一个示例中类似的 HTTP 请求,但是在应用程序加载之前,就等待请求返回并更新存储。


请记住,Vuex 存储只是具有某些属性和方法的一个对象,所以可以将它和其他任何 JavaScript 对象一样来看待。


我们可以将存储导入到 main.js 文件(或者你自己确定的应用程序入口点)中,并在挂载应用程序之前调用 HTTP 请求:


import Vue from "vue"import store from "./store"import App from "./App.vue"fetch('/user')  .then(r => r.json())  .then((user) => {    store.commit('setUser', user)    new Vue({      store,      render: (h) => h(App),    }).$mount("#app")  })  .catch((error) => {    // Don't forget to handle this  })
复制代码


这种方法的好处是,在应用程序加载之前,就会将需要从 API 获取的所有数据都预加载到全局存储中。这是避免前面提到的问题跳转或管理某些加载逻辑的便捷方法。


然而……


这里有一个警告需要注意。的确,你不必担心在 HTTP 请求挂起时应该显示什么加载提示,但与此同时,你的应用不会显示任何内容。如果你的应用程序是单页应用程序,则你的用户可能会一直盯着空白的页面,直到请求返回为止。


因此,你并没有真正解决延迟问题,只是选择了在用户等待数据时要显示哪种 UI 体验。


结束语


哪种方法更好?我没有什么确切的结论。实际上,你可以同时使用这三种方法,具体取决于你要获取的数据类型以及应用程序的需求。


我还应该提一下,我的示例是在做 fetch 请求,然后使用 Vuex 突变直接提交到存储。而你可以轻松地使用 Vuex 动作来实现 fetch。你还可以将这些原理应用于其他任何状态管理工具,例如 Vue.observable。


原文链接:


3 Ways Prepopulate Vue.js Global Stores State


2020-12-25 09:161444

评论

发布
暂无评论
发现更多内容

零基础也能转型!MES系统助力中小企业数字化转型

万界星空科技

数字化转型 数字化 制造业 mes 万界星空科技mes

如何实现RAG与MCP集成

电子尖叫食人鱼

rag

人工智能产品测试 | 特征的概念:离散与连续

测试人

人工智能

超实用!Dify快速接入本地MCP服务

王磊

2025年测试人必看:AI+Playwright让自动化测试效率飙升200%?

测试人

人工智能 软件测试

功能齐全Mac用户必备的FTP客户端Transmit 5中文版

Rose

音乐可视化编程 Cycling '74 Max for mac 9.0.7(含 RNBO)

Rose

BeeWorks:私有化即时通讯,筑牢企业信息安全防线

BeeWorks

即时通讯 IM 私有化部署

七牛云存储基于时间戳防盗链的算法JAVA实现

Chris Zhang

Java 七牛云存储 安全 防盗链

CST软件对粒子枪仿真和Track Solver追踪求解

思茂信息

cst电磁仿真 CST软件 CST Studio Suite

Sketch 2025.1详细新功能介绍

Rose

Vantage荣膺"最佳赛车运动赞助商"殊荣 携手Scuderia Ferrari HP共创辉煌

财见

库存搞不好,利润掉一截!别让库存吃掉你的利润!

积木链小链

数字化转型 智能制造 库存管理

恒普达:科技赋能公共安全,智领数字时代新未来

极客天地

存得快查得准,但就是算不动?试试时序数据库 TDengine × Spark 的组合拳

TDengine

数据库 tdengine 物联网 时序数据库

VMmark 4.0.3 - 虚拟化平台基准测试

sysin

VMmark

艺术品NFT系统的运营

北京木奇移动技术有限公司

区块链技术 软件外包公司 音乐NFT

Spring AI 结合DeepSeek使用教程

知识浅谈

低代码时代,让“双手”再解放一点

秃头小帅oi

Studio 3T 2025.10 发布,社区版重磅回归

sysin

mongodb

通义灵码 AI IDE 正式上线,智能体自动写代码,首创自动记忆,工程感知全面升级

阿里巴巴云原生

AI 通义灵码

AI 不再是 PPT:它在帮企业做发电预测、运维预警和用电规划

TDengine

数据库 tdengine 物联网 时序数据库

产品叫好又叫座的关键:管理者别再困在「研发工程师依赖症」里

IPD产品研发管理

产品 产品经理 产品设计 产品架构

Redis主从复制详解

不在线第一只蜗牛

redis

AI技术实现英语口语陪练APP

北京木奇移动技术有限公司

软件外包公司 APP外包公司 AI英语学习

游戏公司如何同时管好上百个游戏项目?

禅道项目管理

项目管理 游戏开发 看板 项目管理软件 游戏行业

全国首发!数造科技发布大数据产品,助力广州政务服务与营商环境升级

数造万象

人工智能 数据资产 科技 政务 热点

【拥抱鸿蒙】HarmonyOS NEXT实现双路预览并识别文字

郑知鱼

华为 鸿蒙 OCR 移动端开发 HarmonyOS NEXT

LlamaFactory × 多模态RAG × Chat-BI,万字长文揭秘RAG进化迷踪,打造专业AI助手!

商汤万象开发者

AI 大模型 LLM

NITF 2025 聚焦核电数智化,时序数据库 TDengine 分享亿级数据处理方案

TDengine

tdengine 时序数据库 数据库·

【FAQ】HarmonyOS SDK 闭源开放能力 —Account Kit(5)

HarmonyOS SDK

harmoyos

预填充Vue.js全局存储状态的三种方法_语言 & 开发_Austin Gil_InfoQ精选文章