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

时间:2022-09-18 18:03:14

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

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

VUE入门并不是很难,假设你已经熟悉实现 Vuex。这篇文章毕竟不是关于新手的。如果您需要,那么我建议您查看文档。

Vuex 的使用使得的管理全局数据存储变得更加简单,对于以下示例,假设有一个类似以下内容的存储:

  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. Vue.use(Vuex) 
  4. const store = new Vuex.Store({ 
  5.   state: { 
  6.     user: null
  7.   }, 
  8.   mutations: { 
  9.     setUser (state, user) { 
  10.       state.user = user 
  11.     } 
  12.   }, 
  13. }) 

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

  1. <template> 
  2.   <div> 
  3.     <p v-if="user">Hi {{ user.name }}, welcome back!</p> 
  4.     <p v-else>You should probably log in.</p> 
  5.   </div> 
  6. </template> 
  7.  
  8. <script> 
  9. export default { 
  10.   computed { 
  11.     user() { 
  12.       return this.$store.state.user 
  13.     } 
  14.   } 
  15. </script> 

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

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

设置初始状态

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

  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3.  
  4. Vue.use(Vuex) 
  5.  
  6. const store = new Vuex.Store({ 
  7.   state: { 
  8.     user: { name: "Austin" } 
  9.   }, 
  10.   mutations: { 
  11.     setUser (user) { 
  12.       state.user = user 
  13.     } 
  14.   } 
  15. }) 

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

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

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

  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3.  
  4. Vue.use(Vuex) 
  5.  
  6. const store = new Vuex.Store({ 
  7.   state: { 
  8.     user: localStorage.get('user'
  9.   }, 
  10.   mutations: { 
  11.     setUser (user) { 
  12.       state.user = user 
  13.     } 
  14.   } 
  15. }) 

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

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

安装应用程序时请求数据

现在假设,不将数据存储在本地存储中。我们的下一个操作可能是将初始状态留空,并允许应用程序挂载。安装应用程序后,我们可以向服务器发出一些 HTTP 请求以获取数据,然后更新全局状态:

  1. <template> 
  2.   <div> 
  3.     <p v-if="user">Hi {{ user.name }}, welcome back!</p> 
  4.     <p v-else>You should probably log in.</p> 
  5.   </div> 
  6. </template> 
  7. <script> 
  8. export default { 
  9.   computed { 
  10.     user() { 
  11.       return this.$store.state.user 
  12.     } 
  13.   }, 
  14.   async mounted() { 
  15.     const user = await getUser() // Assume getUser returns a user object with a name property
  16.     this.$store.commit('setUser', user) 
  17.   } 
  18. </script> 

但是,现在有一个奇怪的用户体验。应用程序将加载并发送请求,但当用户等待请求返回时,会看到“您可能应该登录”。当请求返回时,假设有一个登录的会话,该消息会迅速更改为“嗨{{ user.name }},欢迎回来!”。这看起来会显得奇怪。

为了解决这个问题,我们只需在请求发出时显示加载元素:

  1. <template> 
  2.   <div> 
  3.     <p v-if="loading">Loading...</p> 
  4.     <p v-else-if="user">Hi {{ user.name }}, welcome back!</p> 
  5.     <p v-else>You should probably log in.</p> 
  6.   </div> 
  7. </template> 
  8.  
  9. <script> 
  10. export default { 
  11.   data: () => ({ 
  12.     loading: false
  13.   }), 
  14.   computed { 
  15.     user() { 
  16.       return this.$store.state.user 
  17.     } 
  18.   }, 
  19.   async mounted() { 
  20.     this.loading = true
  21.     const user = await fetch('/user').then(r => r.json()) // Assume getUser returns a user object with a name property
  22.     this.$store.commit('setUser', user) 
  23.     this.loading = false
  24.   } 
  25. </script> 

记住,这是一个非常简单的示例。在您的应用程序中,您可能有一个用于加载动画的专用组件,并且可能有一个<router-view>组件来代替此处的用户消息。还可以选择从 Vuex 操作发出该 HTTP 请求,这个概念仍然适用。

在加载应用承载之前请求数据

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

Vuex 存储只是一个具有一些属性和方法的对象,可以将其视为任何其他 JavaScript 对象。

将我们的存储导入main.js文件(或任何应用程序的入口点)并在安装应用程序之前调用HTTP 请求:

  1. import Vue from "vue"
  2. import store from "./store"
  3. import App from "./App.vue"
  4. fetch('/user'
  5.   .then(r => r.json()) 
  6.   .then((user) => { 
  7.     store.commit('setUser', user) 
  8.     new Vue({ 
  9.       store, 
  10.       render: (h) => h(App), 
  11.     }).$mount("#app"
  12.   }) 
  13.   .catch((error) => { 
  14.     // Don't forget to handle this
  15.   }) 

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

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

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

结语

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

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

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

原文链接:https://dzone.com/articles/3-ways-to-prepopulate-your-vuejs-global-stores-sta