此章节涉及到的内容:
1、vuex的store用法
2、vuex的相关操作和核心用法
什么是 vuex?
vuex 是一个状态管理模式,可以用来共享数据。
以淘宝为例,如果在首页登录了自己的账户,当点击首页的链接跳转到其他页面时,仍然会是登录状态。
这就是vuex,而实现这些的是因为用到了vuex中的store(仓库),这个 store 会让各个组件获取到你当前的状态,根据状态去判断渲染出什么。
store 基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。
什么情况下要用 vuex?
判断方式很简单,当你不需要用到 vuex 就把项目的所有功能全部都实现了的时候,就不需要用了。
反之就需要用 vuex !
先回顾一下之前父子组件之间的数据传递
直接看例子,都是在src/components文件夹下
parent.vue 父组件
<template>
<div>
<span>这里都是父组件</span><br><br>
{{fromSon}}
<hr>
<!-- 自定义一个handle事件来接受子组件的数据 -->
<son v-bind:msg="toSonMsg" v-on:handle="getMsgFromSon"></son>
</div>
</template>
<script>
//父组件传递数据到子组件,需要先引入子组件
import son from "./son";
export default {
name: "parent",
data: function() {
return {
toSonMsg: "我是父组件传递过来的内容",
fromSon: ""
};
},
components: {
son
},
methods: {
getMsgFromSon: function(value) {
this.fromSon = value;
}
}
};
</script>
son.vue 子组件
<template>
<div>
<span>这里都是子组件</span><br><br>
{{msg}}
<button v-on:click="toFaMsg">向父组件传递数据</button>
</div>
</template>
<script>
export default {
name: "son",
data:function(){
return {
sonMsg:'我是子组件传递过来的内容'
}
},
//子组件接收数据
props: {
msg: {
type: String,
default: ""
}
},
//子组件向父组件传递数据
methods:{
toFaMsg:function(){
//使用this,$emit()传递数据,第一个写事件名,第二个写要传递的参数
this.$emit('handle',this.sonMsg)
}
}
};
</script>
HelloWorld.vue 显示页面内容的组件
<template>
<div class="hello">
<parent/>
</div>
</template>
<script>
//将父组件引入就可以看到子组件
import parent from "./parent";
export default {
name: "HelloWorld",
data() {
return {
msg: "Welcome to Your Vue.js App"
};
},
//记得在这里也要注入进去
components: {
parent
}
};
</script>
使用npm run dev进入项目,地址栏输入localhost:8080,并且点击按钮可以看到显示的内容,就表示传递成功
1、vuex的基本用法
需求:outter.vue | parent.vue | son.vue 三个组件之间共享数据
1、安装vuex,进入到项目目录下
npm install vuex
2、引入vuex,在src下的main.js中引入,并且创建状态仓库
import Vue from 'vue'
import App from './App'
import router from './router'
//引入vuex
import Vuex from 'vuex'
Vue.config.productionTip = false
//并且调用它
Vue.use(Vuex)
//创建一个状态仓库 store,后面的 Vuex.Store 首字母一定要大写
var store = new Vuex.Store({
//用state来记录状态,这个state不要乱改
state:{
num:88
}
})
//创建好了store仓库之后,记得在这里引入一下
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
3、通过this.$sore.state.XXX直接拿到需要的数据
parent.vue中
<template>
<div>
<span>这里都是父组件</span><br><br>
{{fromSon}}<br><br>
这里是父组件通过store获取的数据num:{{getNum}}
<hr>
<!-- 自定义一个handle事件来接受子组件的数据 -->
<son v-bind:msg="toSonMsg" v-on:handle="getMsgFromSon"></son>
</div>
</template>
<script>
//父组件传递数据到子组件,需要先引入子组件
import son from "./son";
export default {
name: "parent",
data: function() {
return {
toSonMsg: "我是父组件传递过来的内容",
fromSon: ""
};
},
components: {
son
},
methods: {
getMsgFromSon: function(value) {
this.fromSon = value;
}
},
//父组件中是用计算属性去拿到 store 仓库的数据
computed:{
getNum:function(){
return this.$store.state.num
}
}
};
</script>
son.vue中
<template>
<div>
<span>这里都是子组件</span><br><br>
{{msg}} <br><br>
这里是子组件通过
store获取的数据num:{{getNum}} <br><br>
<button v-on:click="toFaMsg">向父组件传递数据</button>
</div>
</template>
<script>
export default {
name: "son",
data:function(){
return {
sonMsg:'我是子组件传递过来的内容'
}
},
//子组件接收数据
props: {
msg: {
type: String,
default: ""
}
},
//子组件向父组件传递数据
methods:{
toFaMsg:function(){
//使用this,$emit()传递数据,第一个写事件名,第二个写要传递的参数
this.$emit('handle',this.sonMsg)
}
},
//子组件中是用计算属性去拿到 store 仓库的数据
computed:{
getNum:function(){
return this.$store.state.num
}
}
};
</script>
outter.vue中
<template>
<div>
<hr>
这里是outter组件通过store获取的数据num:{{getNum}}
</div>
</template>
<script>
export default {
name: "parent",
data: function() {
return {
};
},
//outter组件中是用计算属性去拿到 store 仓库的数据
computed:{
getNum:function(){
return this.$store.state.num
}
}
};
</script>
HelloWorld.vue 中显示出来
<template>
<div class="hello">
<parent/>
<outter/>
</div>
</template>
<script>
//将父组件引入就可以看到字组件
import parent from "./parent";
import outter from "./outter"
export default {
name: "HelloWorld",
data() {
return {
msg: "Welcome to Your Vue.js App"
};
},
//记得在这里也要注入进去
components: {
parent,
outter
}
};
</script>
结果,全部能够拿到store里面的num的数据:
2、vuex的相关操作和核心用法
在实际过程中不仅是需要获取,同时经常需要改变它的状态,比如淘宝购物车,把这个网页的宝贝添加进购物车,在那个网页的宝贝也添加进购物车,这是需要状态的改变的。
那么改变的时候实际上进行了那些操作呢?看下面
vuex状态的管理流程:
view → actions → mutations → state → view
除了能够获取状态如何改变状态呢?
需求:让parent组件,son组件,outter组件点击后分别可以改变state仓库的状态
第一种方法具体实现过程:
(下面的代码就是基于上面的整体代码实现的)
1、现在main.js中定义mutations事件,来改变store仓库的状态
//创建一个状态仓库 store,后面的 Vuex.Store 首字母一定要大写
var store = new Vuex.Store({
//用state来记录状态,这个state不要乱改
state:{
num:88
},
//定义mutations事件,来改变state仓库的状态
mutations:{
//定义一个increase方法,点击按钮,每次让num + 1,传统写法
increase:function(state){
state.num++
},
//定义一个decrease方法,点击按钮,每次让num - 1,es6写法,":function"这个可以省略
decrease(state){
state.num--
}
//获取方法: this.$store.commit(xxx),这个xxx是mutations中定义的方法
}
})
2、在parent | son | outter 组件中引入
parent.vue
<button v-on:click="pAdd">父组件---改变状态按钮</button>
<script>
methods:{
//添加改变组件状态的方法,记住传递的一定是字符串,加''
pAdd: function() {
this.$store.commit('increase');
}
}
</script>
son.vue
<button v-on:click="sAdd">子组件---改变状态按钮</button>
<script>
methods:{
//添加改变组件状态的方法,记住传递的一定是字符串,加''
sAdd: function() {
this.$store.commit('increase');
}
}
</script>
outter.vue
<button v-on:click="oAdd">outter组件---改变状态按钮</button>
<script>
methods:{
//添加改变组件状态的方法,记住传递的一定是字符串,加''
oAdd: function() {
this.$store.commit('increase');
}
}
</script>
3、结果:
只要点击这三个按钮,先出出来的数值就会加1,就代表改变状态成功了。
第二种方法具体实现过程
还有一种方法可以修改状态,使用 actions
注意:actions 提交的是 mutations ,而不是直接改变状态。
同时 actions 可以包含异步操作(setTimeout等),但是 mutations 只能包含同步操作。
1、main.js中加入actions
需要先定义好 mutations ,再去定义actions
//定义mutations事件,来改变state仓库的状态
mutations:{
//定义一个increase方法,点击按钮,每次让num + 1,传统写法
increase:function(state){
state.num++
},
//定义一个decrease方法,点击按钮,每次让num - 1,es6写法,":function"这个可以省略
decrease(state){
state.num--
}
//获取方法: this.$store.commit(xxx),这个xxx是mutations中定义的方法
},
//定义actions来改变state仓库的状态,但是这里需要传一个参数 context(上下文对象)
actions:{
//并且actions只能对mutations进行操作,不能直接操作state
decreaseAction:function(context){
//这里传入的必须是在上面mutations写好了的方法
context.commit('decrease')
}
//获取方法:this.$store.dispatch(xxx),这个xxx是actions中定义的
}
2、在parent | son | outter 组件中引入
parent.vue
<button v-on:click="pReduce">父组件---改变状态按钮(actions)</button>
<script>
methods: {
//使用mutations改变组件状态的方法,记住传递的一定是字符串,加''
pAdd: function() {
this.$store.commit('increase');
},
//使用actions改变组件状态
pReduce:function(){
this.$store.dispatch('decreaseAction')
}
},
</script>
son.vue
<button v-on:click="sReduce">子组件---改变状态按钮(actions)</button>
<script>
methods: {
//使用mutations改变状态方法
sAdd: function() {
this.$store.commit('increase');
},
//使用actions改变组件状态
sReduce:function(){
this.$store.dispatch('decreaseAction')
}
},
</script>
outter.vue
<button v-on:click="oReduce">outter组件---改变状态按钮(actions)</button>
<script>
methods: {
//使用mutations改变状态方法
oAdd:function(){
this.$store.commit('increase')
},
//使用actions改变组件状态
oReduce:function(){
this.$store.dispatch('decreaseAction')
}
</script>
3、结果
只要点击这个actions按钮,上面的数字就会减1,就代表使用actions修改成功了。
4、最后还有一个 getters
getters 可以对拿到的状态进行处理,比如去银行取钱,不会取到负数,最多取到余额0,这个余额0就需要在 getters 里面先处理好
与mutations,actions是同一级的
4.1 main.js中
//定义getters,这个getters可以对状态做处理,做限制
getters: {
//这里传的参数也是 state ,并且在实际业务中是通过在getters里面定义的方法来拿到state的状态的
getNum: function (state) {
return state.num >= 0 ? state.num : 0
}
//获取方法:this.$store.getters.xxx ,这个xxx是在getters里面定义的方法
}
4.2 在parent | son | outter 组件中引入
因为这里用到getters的地方就是computed计算属性内
parent.vue
//父组件中是用计算属性去拿到 store 仓库的数据
computed: {
getNum: function() {
// return this.$store.state.num;
//这里通过getters里面定义的拿
return this.$store.getters.getNum
}
}
son.vue
//子组件中是用计算属性去拿到 store 仓库的数据
computed: {
getNum: function() {
// return this.$store.state.num;
//这里通过getters里面定义的拿
return this.$store.getters.getNum
}
}
outter.vue
//outter组件中是用计算属性去拿到 store 仓库的数据
computed: {
getNum: function() {
// return this.$store.state.num;
//这里通过getters里面定义的拿
return this.$store.getters.getNum
}
},
4.3 结果
这里一直减的话,会减到0就减不下去了,这就代表 getters 设置状态成功!