【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】