文章目录
本篇博客跟学视频链接:Vuex从入门到实战_bilibili
1. 组件之间数据共享
父向子传值:v-bind 属性绑定
子向父传值:v-on 事件绑定
兄弟组件之间共享数据:EventBus
$on 接收数据的那个组件
$emit 发送数据的那个组件
2. Vuex概述
- 实现组件全局(数据)管理的一种机制,可以方便的实现组件之间共享数据,不同于上述三种传递值的方式。
- 可以把vuex当成一个store仓库,可以集中管理共享的数据,并且存储在vuex中的数据都是响应式的,数据与页面同步。
- 一般情况下,只有组件之间共享的数据,才有必要存储到vuex中;对于组件中的私有数据,依旧存储在组件自身的data中。
3.Vuex基本使用
1)安装vuex依赖
npm install vuex --save
2)导入vuex包
import Vuex from 'vuex'
Vue.use(Vuex)
3)创建store对象
const store = new Vuex.Store({
// state 中存放全局共享的数据
state: {count:0}
})
4)store对象挂载到vue实例中
new Vue({
el: '#app',
render: h=>h(app),
router,
// 创建的共享数据挂载到vue实例
// 所有组件能够直接从store中获取到全局的数据
store
})
5)利用vue ui脚手架创建vue项目
- 详见另一篇文档
3. 项目基础知识
1)格式化
- 项目下创建文件.prettierrc,应与.gitignore同级,两句代码分别代表:去除分号,用单引号替换双引号。
{
"semi": false,
"singleQuote": true
}
2)git提交
4. Vuex核心概念
1)State
- State 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 State 中进行存储。
// 创建store数据源,提供唯一公共数据
const store = new Vuex.Store({
state: { count: 0 }
})
1:访问State方法一
- 注意在唯一根组件template中,可以省略this不写
2:访问State方法二
- 导入mapState并把所需要的State域中的属性映射为当前组件的计算属性。
<template>
<div>
<h3>当前最新的count值为:{{ count }}}</h3>
<button>-1</button>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
data() {
return {}
},
// 把State全局域中的数据映射为我当前组件的计算属性
computed: {
...mapState(['count'])
}
}
</script>
2)Mutation
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// 定义唯一的state域变量
state: {
count: 0
},
// 只有 mutations 中定义的函数,才有权利修改 state 中的数据
// 注意mutations中的方法第一个参数必须是state而且必须带,否则无法调用state中的变量
mutations: {
// 不带参mutations
add(state) {
state.count++
},
// 带参数的mutations
addN(state, step) {
state.count += step
},
sub(state) {
state.count--
},
subN(state, step) {
state.count -= step
}
}
})
1:触发Mutation方法一
- 在vuex中不允许组件直接去修改全局域中的数据,必须通过Mutation来变更Store中的数据。 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化(可以监控是谁更改了State)。
addition.vue
<template>
<div>
<!-- <h3>当前最新的count值为:{{$store.state.count}}</h3> -->
<h3>{{$store.getters.showNum}}</h3>
<!-- 点击该按钮调用Mutation使count值+1 -->
<button @click="btnHandler1">+1</button>
<!-- 点击该按钮调用Mutation使count值+N -->
<button @click="btnHandler2">+N</button>
</div>
</template>
<script>
export default {
data() {
return {}
},
// methods方法实际调用的是vuex中的Mutation来改变State域中的值
methods: {
btnHandler1() {
this.$store.commit('add')
// this.$store.count++; // 不要在本组件中直接修改State域中数据的值
},
btnHandler2() {
// commit 的作用,就是调用 某个 mutation 函数
this.$store.commit('addN', 3)
},
}
}
</script>
2:触发Mutation方法二
- 同样的,用一个mapMutations将全局的Mutation函数映射到本组件中。
subtraction.vue
<template>
<div>
<!-- <h3>当前最新的count值为:{{count}}</h3> -->
<h3>{{showNum}}</h3>
<button @click="btnHandler1">-1</button>
<button @click="subN(3)">-N</button>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'
export default {
data() {
return {}
},
computed: {
...mapState(['count']),
...mapGetters(['showNum'])
},
methods: {
...mapMutations(['sub', 'subN']), // 注册sub和subN函数
btnHandler1() {
this.sub()
}
}
}
</script>
3)Action
- 如果我们想书写一个异步操作,如单击+1后等待1s后state域中的值才会发生变化,我们可以用js中的定时器来实现,但是vue不能在mutations函数中执行异步操作,此时我们引入Action。
- Action 用于处理异步任务。如果通过异步操作变更数据,必须通过 Action,而不能使用 Mutation,但是在 Action 中还是要通过触发Mutation 的方式间接变更数据。
1:触发Action方式一
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// 定义唯一的state域变量
state: {
count: 0
},
mutations: {
add(state) {
// 不要在 mutations 函数中,执行异步操作
// setTimeout(() => {
// state.count++
// }, 1000)
state.count++
},
addN(state, step) {
state.count += step
},
sub(state) {
state.count--
},
subN(state, step) {
state.count -= step
}
},
actions: {
addAsync(context) {
setTimeout(() => {
// 在 actions 中,不能直接修改 state 中的数据;
// 必须通过 context.commit() 触发某个 mutation 才行
context.commit('add')
}, 1000)
},
addNAsync(context, step) {
setTimeout(() => {
context.commit('addN', step)
}, 1000)
},
})
- commit函数用于触发Mutations,而dispatch函数用于触发Action,注意Action无法直接修改state域中的值,还是必须通过Mutations来间接的修改state域中的值。
Addition.vue
<template>
<div>
<!-- <h3>当前最新的count值为:{{$store.state.count}}</h3> -->
<h3>{{$store.getters.showNum}}</h3>
<!-- 点击该按钮调用Mutation使count值+1 -->
<button @click="btnHandler1">+1</button>
<!-- 点击该按钮调用Mutation使count值+N -->
<button @click="btnHandler2">+N</button>
<button @click="btnHandler3">+1 Async</button>
<button @click="btnHandler4">+N Async</button>
</div>
</template>
<script>
export default {
data() {
return {}
},
// methods方法实际调用的是vuex中的Mutation来改变State域中的值
methods: {
btnHandler1() {
this.$store.commit('add');
// this.$store.count++; // 不要在本组件中直接修改State域中数据的值
},
btnHandler2() {
// commit 的作用,就是调用 某个 mutation 函数
this.$store.commit('addN', 3)
},
// 异步地让 count 自增 +1
btnHandler3() {
// 这里的 dispatch 函数,专门用来触发 action
this.$store.dispatch('addAsync')
},
btnHandler4() {
this.$store.dispatch('addNAsync', 5)
}
}
}
</script>
2:触发Action方法二
- 同样的可以使用mapActions数据结构来引入在store.js中注册过的Action和mapState、mapMutations同理。注意用mapMutations、mapActions注册过的方法可以直接根据函数名来调用。
Subtraction.vue
<template>
<div>
<!-- <h3>当前最新的count值为:{{count}}</h3> -->
<h3>{{ showNum }}</h3>
<button @click="sub">-1</button>
<button @click="subN(3)">-N</button>
<button @click="subAsync">-1 Async</button>
<button @click="subNAsync(5)">-N Async</button>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'
export default {
data() {
return {}
},
computed: {
...mapState(['count']),
},
methods: {
...mapMutations(['sub', 'subN']),
...mapActions(['subAsync', 'subNAsync']),
// 注意这里的subAsync和subNAsync都可以直接作为函数被调用,不用像btnHandler1一样新开一个函数来调用
// 由map注册过的方法都可以直接调用
btnHandler1() {
this.sub()
}
}
}
</script>
4)Getter
- Getter用于对Store中的数据进行加工处理并形成新的数据,类似于Vue中的计算属性,Store中的数据发生变化,Getter中的数据也发生变化,存在一个响应关系。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// 定义唯一的state域变量
state: {
count: 0
},
mutations: {
···
},
actions: {
···
},
// getter方法模拟显示当前最新的值
getters: {
showNum(state) {
return '当前最新的数量是【' + state.count + '】'
}
}
})
1:使用getters的两种方法
5. Vuex综合案例
- 详见于 vuex_demo2,里面有我非常详细的注释。
- 注意打开新项目时应当删除module_nodes和package-lock.json两个文件夹,并输入指令npm i(即install)和npm run serve来启动服务。