写点什么

预填充 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:161530

评论

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

分布式架构基础

天翼云开发者社区

中间件 计算

节能LED显示技术:点亮未来

Dylan

广告 LED LED display LED显示屏 LED屏幕

存算分离架构重塑政务数据治理:福建大数据基于 Databend 构建一体化公共数据平台的实践探索

Databend

海外APP的开发流程

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

软件外包公司 APP外包公司 海外APP

看到了 SQL 中 order by 3 desc,1 直接愣了一下。知道原因后,直接想骂人!

左诗右码

【顶会论文】时序数据库 Apache IoTDB 论文获 VLDB 2025 录用,集群秒级扩容性能“解密”

Apache IoTDB

工业管理 项目管理经验总结(7)

万里无云万里天

项目管理 工业 工厂运维

qData 数据中台【开源版】发布 1.0.4 版本,全面升级数据清洗与资产管理能力

千桐科技

数据中台 qData 开源数据中台 Java数据中台 千数平台

黑龙江等保测评安全技术服务:打造数字时代安全堡垒的秘密武器

等保测评

R8疑难杂症分析实战:外联优化设计缺陷引起的崩溃|得物技术

得物技术

android 性能优化 编译器 编译器 加速器 编程语言

【 HarmonyOS 】错误描述:The certificate has expired! 鸿蒙证书过期如何解决?

GeorgeGcs

破人才瓶颈、促生态共赢 ——2025 鸿蒙生态大会人才发展分论坛亮点纷呈

最新动态

崩了!Nacos升级到3.0竟不能用了,哭死!

王磊

哈尔滨三级等保:数字时代的安全 “定海神针

等保测评

Google 发布了Nano Banana编写最佳提示词,提供了10种场景

程序员海军

AI 设计 AIGC Nano Banana Gemini 2.5

数据分析与AI丨产品全生命周期的数据分析与AI提效案例

Altair RapidMiner

人工智能 AI 数据分析 制造业 RapidMiner

【HarmonyOS】一步解决弹框集成-快速弹框QuickDialog使用详解

GeorgeGcs

Karma无线安全工具:探针响应与网络诱捕技术解析

qife122

网络安全 渗透测试

面向对象设计与设计模式实战指南

qife122

设计模式 低层设计

让天下没有难查的故障:2025 阿里云 AI 原生编程挑战赛正式启动

阿里云云效

阿里云 云原生 云原生编程挑战赛

分布式系统-秒杀

天翼云开发者社区

大数据 安全 中间件

《小K闪电课堂》:秒懂 KaiwuDB/KWDB 数据库技术内核

KaiwuDB

数据库 数据库教程

在LXC容器中安装Bitwarden密码管理器的完整指南

qife122

Docker Bitwarden

kafka数据同步到mysql

天翼云开发者社区

数据库复制

技术文章

qife122

人工智能 openai

基于 Amazon Q Developer+Remote MCP 访问 Amazon Redshift

亚马逊云科技 (Amazon Web Services)

大数据-85 Spark Action 操作详解:从 Collect 到存储的全景解析

武子康

Java 大数据 flink spark 分布式

让天下没有难查的故障:2025 阿里云 AI 原生编程挑战赛正式启动

阿里巴巴云原生

阿里云 云原生 变成挑战赛

2025 HarmonyOS创新赛线上解读会成功举办 助力开发者把握生态机遇

最新动态

大庆企业选等保测评公司,牢记这 5 个筛选要点

等保测评

聊聊 Webpack 那些安全事儿:打包风险与防护小技巧

权说安全

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