Vuex概述
组件之间共享数据的方式
- 父传子:v-bind 属性绑定
- 子传父:v-on 事件绑定
- 兄弟传值:EventBus
- $on :接受数据的组件
-
Vuex是什么
Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享
使用 Vuex 统一管理状态的好处
能够在 Vuex 中集中管理共享的数据,易于开发和后期维护
- 能够高效地实现组件之间的数据共享,提高开发效率
存储在 Vuex 中的数据都是响应式的,能够实时保持数据与页面的同步
什么数据适合存储到 Vuex 中
一般情况下,只有组件之间共享的数据,才有必要存储到 Vuex 中
- 对于组件中的私有数据,依旧存储在组件自身的 data 中即可
Vuex 的基本使用
安装和使用 vuex 依赖包
安装 vuex 依赖包
npm install vuex --save
导入 vuex 包
import Vuex from 'vuex'
Vue.use(Vuex)
创建 store 对象
const store = new Vuex.Store({
// state 中存放的就是全局共享的数据
state: { count: 0 }
})
将 store 对象挂载到 vue 实例中
new Vue({
el: '#app',
render: h => h(app),
router,
// 将创建的共享数据对象,挂在到 Vue 实例中
// 所有的组件,就可以直接从 store 中获取全局的数据了
store
})
创建 vuex 项目
找到需要创建项目的文件夹目录,在该目录下打开 cmd 命令窗口,输入 vue ui 命令
- 点击创建项目按钮,然后输入依照以下内容进行填写
- 安装预设选择 手动配置, 功能如下:
- Choose Vue version
- Babel
- Vuex
- Router
- Linter / Formatter
- Use config files
- 配置文件选择
State
在 Vue 组件中获得 Vuex 状态
从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:
// 创建一个 State.vue 组件
<template>
<div>
<h1>名字:{{ name }}</h1>
<h2>年龄:{{ age }}</h2>
<h3>数量:{{ num }}</h3>
<input type="text" v-model="num">
</div>
</template>
<script>
// state 在组件中的应用
export default {
computed: {
name () {
return this.$store.state.name
},
age () {
return this.$store.state.age
},
num: {
get () {
return this.$store.state.num
},
set (val) {
this.$store.commit('setNumber', val)
}
}
}
}
</script>
// router/index.js
// 导入 State.vue 组件
import State from '../view/State.vue'
// 将 State.vue 组件挂在到 router/index.js 文件夹下
{ path: '/state', component: 'State' }
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 创建整个项目的数据仓库对象,将多组件共用的数据对象放置到此对象里
export default new Vuex.Store({
// data
state: {
name: 'JiangChen',
age: 18,
num: 0
},
// methods, 在 mutation 里处理状态
mutations: {
addNumber (state) {
state.num += 2
},
setNumber (state, value) {
state.num = value
}
}
})
mapState 辅助函数
当一个组件需要获取多个状态时,将这些状态声明为计算属性会有些重复和冗余。
// 导入 mapState
import { mapState } from 'vuex'
mapState 映射方法1(数组)
<input type="text" :value="num" @input="changeValue">
export default {
computed: mapState(['name', 'age', 'num']),
methods: {
changeValue (e) {
this.$store.commit('setNumber', e.target.value)
}
}
}
mapState 映射方法2
<input type="text" :value="num" @input="changeValue">
export default {
computed: mapState({
// 对象方式
name: 'name',
// 箭头函数方式
age: (state)=>state.age,
num: 'num'
})
}
mapState 映射方法3 ```javascript let mapStateObj = mapState({ // 对象方式 name: ‘name’, // 箭头函数方式 age: (state)=>state.age, num: ‘num’ })
export default { computed: { reverse () { return this.name.split(‘ ‘).reverse().join(‘’) }, …mapStateObj } }
<a name="HDDjB"></a>
# Getter
<a name="ppZHB"></a>
## 在Vuex中通过方法访问Getters状态
从 **store** 实例中读取状态最简单的方法就是在**计算属性**中返回某个状态:
```vue
// 创建一个 Getter.vue 组件
<template>
<div>
<h1>{{ $store.getters.reverseName }}</h1>
<h2>{{ reverseName }}</h2>
</div>
</template>
<script>
export default {
mounted () {
console.log(this);
},
computed: {
reverseName () {
return this.$store.getters.reverseName
}
}
}
</script>
// router/index.js
// 导入 Getter.vue 组件
import Getter from '../view/Getter.vue'
// 将 Getter.vue 组件挂在到 router/index.js 文件夹下
{ path: '/getter', component: 'Getter' }
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 创建整个项目的数据仓库对象,将多组件共用的数据对象放置到此对象里
export default new Vuex.Store({
// 状态
getters: {
reverseName (state) {
return state.name.split('').reverse().join('')
},
minin (state) {
return '123' + state.name
}
}
})
mapGetters 辅助函数
// 导入 mapGetters
import { mapGetter } from 'vuex'
mapGetters 方法1:
export default {
computed: mapGetters(['reverseName', 'mixinName'])
}
mapGetter 方法2: ```javascript import {mapGetters, mapState} from ‘vuex’ let mapGetData = mapGetters([‘reverseName’, ‘mixinName’]); let mapStateData = mapState([‘name’, ‘age’, ‘num’])
export default { computed: { …mapGetData, …mapStateData } }
- mapGetter 方法3:
```html
<!-- Getter.vue -->
<h3>{{ mixinName1 }}</h3>
// Getter.vue
computed: {
...mapGetData,
...mapStateData,
mixinName1() {
return this.$store.getters.mixinName('666')
}
}
// store/index.js
// 状态
getters: {
mixinName (state) {
return (val) => {
return state.name + val
}
}
}
Mutation
-
提交载荷(Payload)
载荷当作参数传入
向 mutation 中的方法提交第二个参数
// Home.vue
<button @click="setAction">setAction</button>
// store/index.js
mutations: {
setNumber (state, value) {
state.num += value
}
}
在 Home.vue 组件中添加 setAction 方法,在方法内部调用 mutations 对象中的 setNumber 方法,并传入对应的参数
setAction 可以改成任意名字
// Home.vue
methods: {
setAction () {
this.$store.commit('setNumber', 5)
}
}
载荷当作对象使用
<button @click="autoAction">autoAction</button>
// store/index.js
mutations: {
autoNumber (state, payload) {
state.num += payload.amount
}
}
- 在 Home.vue 组件中添加 autoAction 方法,在方法内部调用 mutations 对象中的 autoNumber 方法,并传入对应的参数
autoAction 可以改成任意名字
methods: {
autoAction () {
this.$store.commit('autoNumber', {
amount: 3
})
}
}
将方法当作对象传入
<button @click="typeAction">typeAction</button>
// store/index.js
mutations: {
typeNumber (state, payload) {
state.num += payload.amount
}
}
- 在 Home.vue 组件中添加 typeAction 方法,在方法内部调用 mutations 对象中的 typeNumber 方法,并传入对应的参数
typeAction 可以改成任意名字
methods: {
typeAction () {
this.$store.commit('autoNumber', {
amount: 8
})
}
}
在组件中提交 Mutation(mapMutations 辅助函数)
<h1>{{ num }}</h1>
<button @click="autoNumber({amount: 5})">autoNumber</button>
// About.vue 组件中导入 mapMutations, mapState
import { mapMutations, mapState } from 'vuex'
let mapStateObj = mapState(['name', 'age', 'num', 'duanzi'])
let mapMutationsObj = mapMutations(['addNumber', 'setNumber','autoNumber', 'typeNumber'])
export default {
computed: {
...mapStateObj
},
methods: {
...mapMutationsObj
}
}
// store/index.js
export default new Vuex.Store({
// data
state: {
name: 'JiangChen',
age: 18,
num: 0,
duanzi: null
},
// 异步方法
actions: {
setDz (content) {
let httpUrl = 'https://api.apiopen.top/getJoke?page=1&count=10&type=text';
fetch(httpUrl).then(res => res.json()).then(res => {
console.log(res)
console.log(content);
// 通过 muation 来设置 state
content.commit('setDuanzi', res.result)
})
}
}
})
Action
- {{ item.text }}
```javascript
// Action.vue 组件中
export default {
methods: {
getDuanzi () {
this.$store.dispatch('setDz')
}
}
}
// store/index.js
export default new Vuex.Store({
actions: {
setDz (content) {
let httpUrl = 'https://api.apiopen.top/getJoke?page=1&count=10&type=text';
fetch(httpUrl).then(res => res.json()).then(res => {
console.log(res)
console.log(content);
// 通过 muation 来设置 state
content.commit('setDuanzi', res.result)
})
}
}
})
mapActions 辅助函数
<button @click="setDz">setDz</button>
<ul style="text-align: left;">
<li v-for="(item, index) in duanzi" :key="index">{{ item.text }}</li>
</ul>
// Action.vue 组件中
import { mapState, mapActions } from 'vuex'
let mapStateObj = mapState(['duanzi'])
let mapActionsObj = mapActions(['setDz'])
export default {
computed: {
...mapStateObj
},
methods: {
...mapActionsObj
}
}
// store/index.js
export default new Vuex.Store({
// data
state: {
name: 'JiangChen',
age: 18,
num: 0,
duanzi: null
},
// 异步方法
actions: {
setDz (content) {
let httpUrl = 'https://api.apiopen.top/getJoke?page=1&count=10&type=text';
fetch(httpUrl).then(res => res.json()).then(res => {
console.log(res)
console.log(content);
// 通过 muation 来设置 state
content.commit('setDuanzi', res.result)
})
}
}
})
Modules
将 store/index.js 文件中的所有模块全部使用模块化的方式导入
// store/index.js
import state from './state'
import getters from './getters'
import mutations from './mutations'
import actions from './actions'
import buyCar from './buyCar'
export default new Vuex.Store({
// data
state,
// 状态
getters,
// methods, 在 mutation 里处理状态
mutations,
// 异步方法
actions,
// 模块
modules: {
buyCar
}
使用模块化
// BuyCar.vue
<h2 style="color: aqua;">{{ $store.state.buyCar.productNum }}</h2>
<h3>{{ buyCar.productNum }}</h3>
<h4>{{ brief }}</h4>
<button @click="addProNum">addProNum</button><br><br>
<button @click="changeProNum">changeProNum</button>
// BuyCar.vue
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
let mapStateObj = mapState(['buyCar'])
let mapGettersObj = mapGetters(['brief'])
let mapMutationsObj = mapMutations(['addProNum'])
let mapActionsObj = mapActions(['changeProNum'])
export default {
mounted () {
console.log(this);
},
computed: {
...mapStateObj,
...mapGettersObj
},
methods: {
...mapMutationsObj,
...mapActionsObj
}
}