深圳幻海软件技术有限公司 欢迎您!

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

2023-02-27

【51CTO.com快译】当构建Vue.js应用程序并切程序达到一定的规模时,可能会有全局状态管理的需求。方便的是,核心开发团队提供Vuex,它是Vue.js应用程序实际的状态管理库。 VUE入门并不是很难,假设你已经熟悉实现Vuex。这篇文章毕竟不是关于新手的。如果您需要,那么我建议您查

【51CTO.com快译】当构建Vue.js应用程序并切程序达到一定的规模时,可能会有全局状态管理的需求。方便的是,核心开发团队提供Vuex,它是 Vue.js 应用程序实际的状态管理库。 

VUE入门并不是很难,假设你已经熟悉实现 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 
    } 
  }, 
}) 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

存储区的状态从一个空user对象开始, setUser可以更新状态。然后在我们的应用程序中,显示用户详细信息:

<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> 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

因此,当应用程序加载时,如果用户已登录,它会向用户显示“Hi,用户名,welcome back!”的消息。否则,提示用户需要登录,这是一个很小的例子。 

但是,问题来了,假如有几个选项的时候,又该如何解决呢?

设置初始状态

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

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 
    } 
  } 
}) 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

显然,这只有在您提前知道有关用户的详细信息时才可以。在构建应用程序时,我们可能不知道用户的姓名,但还有另一种选择。 

我们可以利用本地存储来保留用户信息的副本。当他们登录时,在 本地存储中设置详细信息,当他们注销时,从本地存储中删除详细信息即可。

当应用加载时,您可以将用户详细信息从本地存储初始状态拉入初始状态:

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 
    } 
  } 
}) 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

如果您使用的数据不需要非常严格的安全限制,那么这样做是可以实现。我建议使用vuex-persistedstate库来帮助实现自动化。 

注意,永远不要将非常敏感的数据(如身份验证令牌)存储在本地存储中,因为它可能会受到XSS的 攻击。因此,上述的例子适用于用户名,但不适用于身份验证令牌之类的东西(它仍然可以是 Vuex,只是不持久化)。

安装应用程序时请求数据

现在假设,不将数据存储在本地存储中。我们的下一个操作可能是将初始状态留空,并允许应用程序挂载。安装应用程序后,我们可以向服务器发出一些 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> 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

但是,现在有一个奇怪的用户体验。应用程序将加载并发送请求,但当用户等待请求返回时,会看到“您可能应该登录”。当请求返回时,假设有一个登录的会话,该消息会迅速更改为“嗨{{ 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> 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.

记住,这是一个非常简单的示例。在您的应用程序中,您可能有一个用于加载动画的专用组件,并且可能有一个<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 
  }) 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

在应用程序加载之前,将需要从 API 获取的任何数据预加载到全局存储中。这种方法可以避免前面提到的janky跳跃或管理某些加载逻辑的问题。
然而,

有一个重要的警告。当 HTTP 请求挂起时,不必担心显示加载微调器,与此同时,应用程序中没有显示任何内容。如果应用程序是单页应用程序,那么用户可能会一直盯着空白页面,直到请求返回。

因此,并没有真正解决延迟问题,只是在等待数据时决定显示什么样的 UI 体验。

结语

对于上述方法,并没有说哪种比较好。实际上,可以根据要获取的数据以及应用程序需要,使用这三种方法。  

还需要提到的是,fetch请求不是使用 Vuex 变体直接提交到存储。您可以同样使用 Vuex 操作来实现fetch请求. 也还可以将这些相同的原则应用于任何其他状态管理工具,例如 Vue.observable。

【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】