Vuex
1 Vuex
- 在vue的项目中,要处理各种各样的数据,这些数据虽然多,但是,从本质上来划分,分为两种数据:
- 组件内部私有的数据(组件之间不会共享私有的数据)
- 组件之间共享的数据(父组件要共享和子组件的数据、子组件要共享给父组件的数据、兄弟组件之间传值)
- 父向子:
v-bind 属性绑定
- 子向父:
v-on 事件绑定机制
- 兄弟组件之间共享数据:
EventBus
$on 接收数据的那个组件
$emit 共享数据的那个组件
- 当组件之间要共享数据的时候最好使用一个全局的数据存储对象来进行控制;
2 什么是Vuex
就是为了实现组件之间数据共享的一种机制/方式;
3 为什么要有Vuex
- 因为使用父子传值或兄弟传值,太麻烦了;不好管理,项目代码写起来太麻烦;
- 当有了 vuex ,想要共享数据,只需要把数据挂载到 vuex 就行;想要获取数据,直接从vuex 上拿就行;
- 当 vuex 中的数据被修改之后,其它引用了此数据的组件,也会被同步更新;
- 注意:只有组件间共享的数据,才有必要存储到vuex中,组件自己私有的数据,还是要存储到自己的data中;
JAVA中是static关键字,内容常驻内存,直接通过类名.属性名 类型.方法名直接访问,但是此种情况下,垃圾回收机制失效
4 如何在项目中使用Vuex
1 认识Vuex
- 运行
npm install vuex
- 在store/index.js中导入 vuex
import Vuex from 'vuex'
- 在store/index.js中使用Vuex
Vue.use(Vuex)
- 在store/index.js中创建store公共状态对象
export default new Vuex.Store({
state: { // state 中存放的,就是全局共享的数据,可以把 state 认为 是组件中的 data
count: 0
}
})
- 在main.js中将 创建的
store
挂载到 vm 实例上
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
- 如果想要在组件中访问全局的数据:
this.$store.state.全局数据名称
2 案例
说明:创建两个组件,一个组件上 添加 ‘+’按钮 并且显示数字;另外一个组件添加 ‘-’按钮并且显示数字,然后点击 + 数值就加,点击-数值就减
第一步:创建Add.vue组件和Minus组件
Add.vue
<template>
<div >
<input type="button" value="+1">
当前最新的count值:
</div>
</template>
Minus.vue
<template>
<div >
<input type="button" value="-1">
当前最新的count值:
</div>
</template>
第二步:为了能够在App.vue页面显示两个组件,需要进行如下设置
在router/index.js中进行如下定义
import add from '@/components/Add.vue'
import minus from '@/components/Minus.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'test',
components:[
add,
minus
]
}
]
在 app.vue 中进行如下配置
<template>
<div id="app">
<router-view name="add" />
<hr>
<router-view name="minus" />
</div>
</template>
<style>
</style>
5 在组件中访问store中state上的属性
1 方式介绍
1.第一种方式(不推荐)
`this.$store.state.数据的名称`
2.第二种方式(推荐)
- 按需导入 mapState 辅助函数:
import { mapState } from "vuex";
- 创建一个computed属性,通过
mapState
,结合...
展开运算符,把需要的状态映射到组件的计算属性中:
computed: {
// 自定义的计算属性
newMsg: function() {
return "----" + this.msg + "------";
},
// 通过 展开运算符,把 state中的数据映射为计算属性,这样,能够让自己的计算属性和store中的属性并存
...mapState(["count"])
}
2 应用
第一步:在store/index.js的state中定义count
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:1
},
mutations: {
},
actions: {
},
modules: {
}
})
第二步:在add.vue组件中显示count
<template>
<div >
<input type="button" value="+1">
当前最新的count值:{{$store.state.count}}
</div>
</template>
这种方式可以显示,但是官方不推荐,官方推荐使用第二种方式
<template>
<div >
<input type="button" value="+1">
<!-- 当前最新的count值:{{$store.state.count}} -->
当前最新的count值:{{count}}
</div>
</template>
<script>
// 从Vuex包中,按需导入一个 mapState 方法
// 作用:是把当前组件中,需要访问的数据,从 store 中,映射为当前组件的计算属性
import { mapState} from 'vuex'
export default {
// 计算属性
computed:{
...mapState(['count'])
}
}
</script>
6 修改store中state上的值–mutations
1 方式介绍
1 第一种方式
使用this.$store.commit('方法名')
来调用 mutations 中的方法
2 第二种方式
- 使用
mapMutaions
来映射方法到methods
中
import { mapMutations } from "vuex";
- 映射 mutations 方法到
methods
中
methods: {
...mapMutations(["add"])
}
2 应用
第一步:直接通过$store.state.count方式去加
<template>
<div >
<input type="button" value="+1" @click="$store.state.count++">
<!-- 当前最新的count值:{{$store.state.count}} -->
当前最新的count值:{{count}}
</div>
</template>
<script>
// 从Vuex包中,按需导入一个 mapState 方法
// 作用:是把当前组件中,需要访问的数据,从 store 中,映射为当前组件的计算属性
import { mapState} from 'vuex'
export default {
// 计算属性
computed:{
...mapState(['count'])
}
}
</script>
第二步:这种方式也可以修改如下
<template>
<div >
<input type="button" value="+1" @click="addHandler()">
<!-- 当前最新的count值:{{$store.state.count}} -->
当前最新的count值:{{count}}
</div>
</template>
<script>
// 从Vuex包中,按需导入一个 mapState 方法
// 作用:是把当前组件中,需要访问的数据,从 store 中,映射为当前组件的计算属性
import { mapState} from 'vuex'
export default {
// 计算属性
computed:{
...mapState(['count'])
},
methods: {
addHandler(){
this.$store.state.count++
}
},
}
</script>
第三步:上述两种方式官方并不推荐,官方推荐使用mustations中定义的方法修改state的数据
所以在store/index.js 的 mutations中定义方法如下
import Vue from 'vue'
import Vuex from 'vuex'
//use 是Vue的静态方法
Vue.use(Vuex)
// 创建一块区域,用来存放公共数据
export default new Vuex.Store({
// 所有的全局需要共享的数据,都应该放到state中
state: {
count:10,
msg:"传智大学,一统江湖,千秋万载"
},
// 在mutations中定义方法,相当于组件的methods
// 对state中的数据的修改 ,只能由mutations操作
mutations: {
// 方法必须要有一个参数,就叫state ,指的就是state
add(state){
state.count++
},
addN(state,step){
state.count += step
}
},
actions: {
},
modules: {
}
})
第四步:在add.vue中调用mutations方法
<template>
<div>
<input type="button" value="+"
@click="addHandler()"
>
<!-- @click="$store.state.count++" -->
<!-- Vuex中的count值:{{$store.state.count}}
{{$store.state.msg}} -->
Vuex中的count值:{{count}}--
{{msg}}
</div>
</template>
<script>
// 按需引入 :在此处引入vuex的state
// {}大括号的作用:解构
// 将vuex中的state映射为计算属性
import {mapState} from 'vuex'
export default {
// 通过mapState访问vuex中的state中的数据
// state相当于计算属性
computed:{
// ... 解析对象成为 计算属性
// ... 展开运算符
...mapState(['count','msg'])
},
methods: {
addHandler(){
// 方式一:Vuex强烈建议 不能直接通过$store的方法去修改state的值
// vuex建议 调用mutations中的方法去修改 state的值
// this.$store.state.count++
// 方式二:调用mutations中的方法
// this.$store.commit("add")
this.$store.commit("addN",10)
}
},
}
</script>
<style scoped>
</style>
第五步:针对上述方式,官方也不推荐,官方推荐mapMutations的方式调用
<template>
<div>
<input type="button" value="+"
@click="addN(100)"
>
<!-- @click="$store.state.count++" -->
<!-- Vuex中的count值:{{$store.state.count}}
{{$store.state.msg}} -->
Vuex中的count值:{{count}}--
{{msg}}
</div>
</template>
<script>
// 按需引入 :在此处引入vuex的state
// {}大括号的作用:解构
// 将vuex中的state映射为计算属性
import {mapState,mapMutations} from 'vuex'
export default {
// 通过mapState访问vuex中的state中的数据
// state相当于计算属性
computed:{
// ... 解析对象成为 计算属性
// ... 展开运算符
...mapState(['count','msg'])
},
methods: {
addHandler(){
// 方式一:Vuex强烈建议 不能直接通过$store的方法去修改state的值
// vuex建议 调用mutations中的方法去修改 state的值
// this.$store.state.count++
// 方式二:调用mutations中的方法, 官方也不是很推荐
// this.$store.commit("add")
// this.$store.commit("addN",10)
},
// 方式三:调用mutations中的方法
...mapMutations(['add','addN'])
},
}
</script>
<style scoped>
</style>
7 定义和使用 actions 来提交异步的操作
1 方式介绍
- 1 使用方式 1
通过this.$store.dispatch('Action方法名称', 参数)
来访问,专门调用actions
中方法的 - 2 使用方式2
使用mapActions
来映射为计算属性:
import { mapActions } from "vuex";
methods: {
...mapActions(["asyncSubtract"])
}
8 定义和使用getters
1 方式介绍
- 使用方式1
通过 this.$store.getters.名称
来访问
- 使用方式2
使用mapGetters
来映射为计算属性:
import { mapState, mapGetters } from "vuex";
computed: {
...mapState(["count"]),
...mapGetters(["countinfo"])
}