安装 Vuex 之后,让我们来创建一个 store。创建过程直截了当——仅需要提供一个初始 state 对象和一些 mutation:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
现在,你可以通过 store.state 来获取状态对象,以及通过 store.commit 方法触发状态变更:
store.commit('increment')
console.log(store.state.count) // -> 1
再次强调,我们通过提交 mutation 的方式,而非直接改变 store.state.count,是因为我们想要更明确地追踪到状态的变化。这个简单的约定能够让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让我们有机会去实现一些能记录每次状态改变,保存状态快照的调试工具。有了它,我们甚至可以实现如时间穿梭般的调试体验。
由于store
中的状态是响应式
的,在组件中调用 store 中的状态
简单到仅需要在计算属性中返回即可
。触发变化
也仅仅是在组件的 methods 中提交 mutation
。
#单一状态树
Vuex 使用单一状态树——是的,
用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源
(SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例
。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
#在 Vue 组件中获得 Vuex 状态
那么我们如何在 Vue 组件中展示状态呢?-----> 计算属性
由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:
// 创建一个 Counter 组件
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return store.state.count
}
}
}
每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。
然而,这种模式导致组件依赖全局状态单例。在模块化的构建系统中,在每个需要使用 state 的组件中需要频繁地导入,并且在测试组件时需要模拟状态。
Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中
(需调用 Vue.use(Vuex)):
const app = new Vue({
el: '#app',
// 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
store,
components: { Counter },
template: `
<div class="app">
<counter></counter>
</div>
`
})
通过在根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到。让我们更新下 Counter 的实现:
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
**state **
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuex</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script type="text/javascript" src="https://unpkg.com/vuex@3.1.1/dist/vuex.js">
</script>
</head>
<body>
<div id="app">
{{msg}}
{{word}}
<home/>
</div>
<!-- home组件template模板 -->
<script type="text/x-template" id='home'>
<div>
<table border='1'>
<tr>
<td>id</td>
<td>姓名</td>
<td>年龄</td>
<td>性别</td>
</tr>
<tr v-for='item in students'>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td>{{item.sex}}</td>
</tr>
</table>
</div>
</script>
<script type="text/javascript">
// 第一步实例化一个store
// 第二步在根组件上挂载store,详见87行
// 第三步在组件或者子组件中使用this.$store.state.students
var store = new Vuex.Store({
state: {
students: [
{
id: 1,
name: '张三',
age: 18,
sex: 'man'
},
{
id: 1,
name: '李四',
age: 18,
sex: 'man'
}
]
}
})
// home组件
var home = {
template: '#home',
data(){
return {
}
},
computed: {
students(){
return this.$store.state.students
}
}
}
// 根组件
var app = new Vue({
data: {
msg: 'hello'
},
computed: {
word(){
return this.msg + ', world'
}
},
// 子组件
components: {
home
},
store
}).$mount('#app')
</script>
</body>
</html>
网友评论