当构建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
- }
- },
- })
存储区的状态从一个空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>
因此,当应用程序加载时,如果用户已登录,它会向用户显示“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
- }
- }
- })
显然,这只有在您提前知道有关用户的详细信息时才可以。在构建应用程序时,我们可能不知道用户的姓名,但还有另一种选择。
我们可以利用本地存储来保留用户信息的副本。当他们登录时,在 本地存储中设置详细信息,当他们注销时,从本地存储中删除详细信息即可。
当应用加载时,您可以将用户详细信息从本地存储初始状态拉入初始状态:
- 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库来帮助实现自动化。
注意,永远不要将非常敏感的数据(如身份验证令牌)存储在本地存储中,因为它可能会受到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>
但是,现在有一个奇怪的用户体验。应用程序将加载并发送请求,但当用户等待请求返回时,会看到“您可能应该登录”。当请求返回时,假设有一个登录的会话,该消息会迅速更改为“嗨{{ 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 获取的任何数据预加载到全局存储中。这种方法可以避免前面提到的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