一. vuex简介
1.Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采 用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
使用Vuex管理数据的好处:
1.能够在 vuex 中集中管理共享的数据,便于开发和后期进行维护。
2.能够高效的实现组件之间的数据共享,提高开发效率。
3.存储在 vuex 中的数据是响应式的,当数据发生改变时,页面中的数据也会同步更新。
二.简单组件传值
2.1 传统组件传值的缺点
props:输入
$emit:输出
输入输出机制有个缺点:页面复杂时,经常需要层层传递数据,因为非父子组件间的交互,只能寻找最近的祖先组件来做中转,同时,输入输出机制还有一个局限性:当不同页面的组件需要进行数据交互时,它就无能为力了
平常开发,这种输入输出的方案也基本满足了但如果有需要跨页面的数据交互或者说,有需要将数据做持久化处理的场景 时;以及如果页面组件层次复杂,存在props 和 $emit 层层传递时,这种方案其实是很难忍受的.
2.2 实现
1.count 变量定义在父组件 App.vue 中
2.两个子组件中都一个一个 prop,名为 count
3.父组件通过 :count 为子组件中的 prop count 传值
4.子组件单击按钮时,通过 $emit,向外广播,告诉父组件应该为 count 变量+1或者 -1
3. 使用 vuex
3.1 安装和配置
安装
当前的项目在创建时,并没有安装 vuex ,所以需要单独安装
npm install vuex
新建store文件
src 目录下创建 store 目录,其中新建 index.js 文件
index.js 文件内容很简单,仅需要提供一个初始 state 对象和一些 mutation
import Vue from 'vue'
import Vuex from 'vuex'
// 这里不要忘了引用插件
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
},
mutations: {
}
})
export default store
引入
为了在 Vue 组件中访问 this.$store property,你需要为 Vue 实例提供创建好的 store。Vuex 提供
了一个从根组件向所有子组件,以 store 选项的方式“注入”该 store 的机制:
修改 main.js
4. vuex 详解
4.1 State
4.1.1 定义satet
State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储
vuex 中的 state 相当于组件中的 data
State中的数据与组件 data 中的数据一样,也是响应式的
import Vue from 'vue'
import Vuex from 'vuex'
// 这里不要忘了引用插件
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
name: '美的冰箱',
price: 120
}
})
export default store
4.1.2 组件中使用 state
在组件中访问 state 中变量,模板中直接使用 $store.state.属性名称获取
<template>
<div class="container">
{{ $store.state.name }}
</div>
</template>
4.1.3 计算属性
<template>
<div class="container">{{ name1 }}--{{ price1 }}</div>
</template>
<script>
export default {
computed: {
name1 () {
return this.$store.state.name
},
price1 () {
return this.$store.state.price
}
}
}
</script>
辅助函数
当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个
问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键:
<template>
<div class="container">{{ name1 }}--{{ price1 }}</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: mapState({
name1: state => state.name,
price1: state => state.price
})
}
</script>
- 我们都知道 computed 的值应该是一个对象,所以 mapState 函数的返回值一定是个对象
- name1 和 price1都是计算属性的名称
- 使用箭头函数时,可以省略 this.$store,而是直接使用 state
更简单一些
上面计算属性后面跟的时一个箭头函数,虽然已经很简单了,但是在辅助函数的帮助下,还可以简化成
一个属性名称
import { mapState } from 'vuex'
export default {
computed: mapState({
name1: 'name',
price1: 'price'
})
}
</script>
再简单一点
当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组
<template>
<div class="container">{{ name }}--{{ price }}</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: mapState(['name', 'price'])
}
</script>
这时候我们的计算属性就不能叫 name1 和 price1 了,而是与 state 中的属性同名
mapState 中不是一个对象了,而是一个数组,数组的元素名称就是你想要使用的 state 中的属性名称
4.2 Getter
Getter用于对Store中的数据进行加工处理形成新的数据
它只会包装Store中保存的数据,并不会修改Store中保存的数据,当Store中的数据发生变化时,Getter
生成的内容也会随之变化
打开store.js文件,添加getters,如下:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '吃饭', done: true },
{ id: 2, text: '睡觉', done: false }
]
},
getters: {
// 定义一个 gettter,用于统计所有完成的事项
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
组件中可以这样直接使用
<template>
<div class="container">{{ $store.getters.doneTodos }}</div>
</template>
也可以使用 mapGetters 辅助函数
<template>
<div class="container">
<p>{{ doneTodos }}}}</p>
<p>{{ todos }}</p>
</div>
</template>
<script>
import { mapState, mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['doneTodos']), // 导入 getters
...mapState(['todos']) // 导入 state
}
}
</script>
总结:getter 是对 state 中的数据做出筛选过滤等,不能改变 state 中的数据,记住一句话:无论何时,都不允许直接操作 state 中的数据。
4.3 Mutation
4.3.1 基本使用
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation
比如想给 todos 中增加一个新的事项,不能直接修改,只能通过 mutation 才可以
mutations: {
add (state) {
state.todos.push({ id: 3, text: '学习', done: false })
}
}
mutation 非常像是一个事件处理函数,不能直接通过 mutation 名字+() 的方式调用,必须是通过
store.commit 触发
组件中编写方法,触发 mutation
4.3.2 提交载荷
所谓载荷(payload)就是参数
在通过 commit 调用 mutaion 的时候可以传递额外的参数
修改 mutation
mutations: {
add (state, item) {
state.todos.push(item)
}
}
组件中调用
methods: {
addItem () {
this.$store.commit('add', { id: 3, text: '载荷', done: false })
}
}
在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读
Mutation 必须是同步函数:也就是说,不要在其中执行ajax 等异步操作
也可以使用 mapMutations辅助函数减少代码