Vue(小码哥王洪元)笔记09vuex,单界面的状态管理,mutation,vuex的核心概念,单一状态树,getters,mutation,module的使用

1、什么是xuex

官方解释:
vuex是一个专门为vue.js开发的状态管理模式
vuex也集成到vue的官方调试工具devtools extiension,提供了诸如零配置的time-travel调试,状态快照导入导出等高级调试功能

状态管理到底是什么?
状态管理模式,集中式存储管理等,可以简单地将其看成把需要多个组件共享的变量全部存储在一个对象里面。然后将这个对象放在顶层的vue实例中,让其他组件可以使用。

可以把状态管理看做是一个公共变量的管理。这个公共变量是事实可更新的。有点类似于vue实例里面的data这里可实时(响应式)更新的

管理什么状态呢?(使用场景)
软件中如果有多个状态,在多个界面间需要共享数据
如用户的登录状态、用户名称、头像、地理位置信息等(如商城里面商品的收藏,购物车中的物品等。)这些状态信息,都可以放在统一的地方,对他进行保存和管理,并且这些信息还都是响应式的

临时插入点思考:

- 1、其实不论是xx.vue组件还是xx.js脚本都在做一件事,就是往外导出export模块,这些导出的模块最终全部要被主入口脚本main.js导入(import)并挂载

- 2、在main.js中导入(注册)的这些模块(路由router,仓库store)又能被各页面通过$router, $stored等魔术变量所拿到,然后把这些模块所包含的data,computed,components,methods等所使用

- 3、main.js作为主入口的脚本,最终也要挂载到首页(el:’#App’),因为vue是一个单页面富应用的东西

2、单界面的状态管理

原理图
从view视图中产生一个actions(如实践),改变状态(如数据改变),状态的改变直接影响view的呈现
在这里插入图片描述

  • 1、安装vuex

项目目录下安装,cmd命令

npm install vuex --save
  • 2、在路由中创建新的路由并use这个插件
    创建一个新的文件夹store,并在store里创建myindx.js(默认访问的话可以创建index.js)
    在myindex.js文件中创建store对象
import Vue from 'vue'
import Vuex from 'vuex'

//1、安装插件
Vue.use(Vuex);

//2、创建vuex对象
const store = new Vuex.Store({
  //在store里面放置的对象
  //状态
  state: {
    counter:1000//数据实际存放在这个state对象的counter里
  },
  mutations: {

  },
  actions: {

  },
  getters: {

  },
  modules: {

  }
})

//3、导出store对象
export default store;
  • 3、在main.js里注册store对象
    只有在main里面注册了,才能个在各个页面中拿到这个对象
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/myindex'//如果不指定具体文件名则默认导入store目录下的

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,//在main里面注册了,才能个在各个页面中拿到这个
  render: h => h(App)
})
  • 4、创建一个HelloVuex.vue组件
    HelloVuex.vue和App.vue组件都要拿到刚才store对象里state中的counter
    调用公共变量使用$store.state.counter

HelloVuex.vue

<template>
  <div>
    <h2>{{$store.state.counter}}</h2>
  </div>
</template>
<script>
export default {
  name:'HelloVuex',
 
}
</script>
<style scoped>

</style>

App.vue
调用公共变量使用$store.state.counter

<template>
  <div id="app">
    <h2>{{message}}</h2>
    <h2 >{{$store.state.counter}}</h2>
    <button @click="addCounter">+</button>
    <button @click="jianCounter">-</button>
    <hello-vuex ></hello-vuex>
  </div>
</template>

<script>
import HelloVuex from './components/HelloVuex'

export default {
  name: 'App',
  data(){
    return{
      message:'我是app组件',
      counter:0
    }
  },
  components:{
    HelloVuex
  },
  methods:{
    addCounter(){

    },
    jianCounter(){

    },
  }
}
</script>

<style>

</style>
3、通过mutation管理状态(state)

在store模块中会 有一个mutations对象,在里面可以放置一些修改state对象内容的方法,这些方法都会包含一个state的参数

以后只要是修改state的内容都必须通过mutation来进行管理(修改)

修改mutation的内容需要使用commit方法,commit带俩参数
在这里插入图片描述

  • 1、在上例基础上修改myindex.js

在store对象里添加mutations对象,并且添加两个方法,这两个方法修改state对象中的counter

import Vue from 'vue'
import Vuex from 'vuex'

//1、安装插件
Vue.use(Vuex);

//2、创建vuex对象
const store = new Vuex.Store({
  //在store里面放置的对象
  //状态
  state: {
    counter:1000
  },
  mutations: {
    //可以定义方法,方法会有一个默认的state参数
    increment() { 
      this.state.counter++
    },
    decrement() { 
      this.state.counter--
    }

  },
  actions: {

  },
  getters: {

  },
  modules: {

  }
})

//3、导出store对象
export default store;
  • 2、在上例基础上修改app.vue
    在methods里填写事件回调函数的代码
  methods:{
    addCounter(){
      //在这个方法中提交mutation,使用commit方法提交
      this.$store.commit('increment');//increment
    },
    jianCounter(){
      //其实就是通过commit来提交一个函数,这个函数恰恰又是在修改state的内容
      this.$store.commit('decrement');

    },
  }

完整app.vue如下

<template>
  <div id="app">
    <h2>{{message}}</h2>
    <h2 >{{$store.state.counter}}</h2>
    <button @click="addCounter">+</button>
    <button @click="jianCounter">-</button>
    <hello-vuex ></hello-vuex>
  </div>
</template>

<script>
import HelloVuex from './components/HelloVuex'

export default {
  name: 'App',
  data(){
    return{
      message:'我是app组件',
      counter:0
    }
  },
  components:{
    HelloVuex
  },
  methods:{
    addCounter(){
      //在这个方法中提交mutation,使用commit方法提交
      this.$store.commit('increment');//increment
    },
    jianCounter(){
      //其实就是通过commit来提交一个函数,这个函数恰恰又是在修改state的内容
      this.$store.commit('decrement');

    },
  }
}
</script>

<style>

</style>
4、vuex的核心概念

State:状态。对应store仓库。了解单一状态树
Getters:读state里的数据(计算之后读取,当然也可以原封不动地读)
Mutations:
Action:异步状态的mutations
Module:

getters可以看做vue实例的compute属性,
mutations可以看做是vue实例的methods属性

5、单一状态树

单一状态树:Single Source of Truth,也可以翻译成单一数据源
其核心思想就是不要让数据分布在各个仓库(store)里,而是只用一个store来存储

6、Getters基本使用
  • 1、myindx.js中创建getters里面的数据修改方法

myindx.js

getters: {
    //这里也有一个默认的state参数
    powerCount(state) { 
      return state.counter*state.counter
    }
  },

完整代码

import Vue from 'vue'
import Vuex from 'vuex'

//1、安装插件
Vue.use(Vuex);

//2、创建vuex对象


const store = new Vuex.Store({
  //在store里面放置的对象
  //状态
  state: {
    counter:1000
  },
  mutations: {
    //可以定义方法,方法会有一个默认的state参数
    increment() { 
      this.state.counter++
    },
    decrement() { 
      this.state.counter--
    }

  },
  actions: {

  },
  getters: {
    //这里也有一个默认的state参数
    powerCount(state) { 
      return state.counter*state.counter
    }
  },
  modules: {

  }
})

//3、导出store对象
export default store;

2、app中是使用getters

<template>
  <div id="app">
    <h2>{{message}}</h2>
    <h2 >{{$store.state.counter}}</h2>
    <button @click="addCounter">+</button>
    <button @click="jianCounter">-</button>
    <hello-vuex></hello-vuex>
    <h2 >App内容:演示getters相关信息</h2>
    <h2>{{$store.getters.powerCount}}</h2>
  </div>
</template>

完整代码

<template>
  <div id="app">
    <h2>{{message}}</h2>
    <h2 >{{$store.state.counter}}</h2>
    <button @click="addCounter">+</button>
    <button @click="jianCounter">-</button>
    <hello-vuex></hello-vuex>
    <h2 >App内容:演示getters相关信息</h2>
    <h2>{{$store.getters.powerCount}}</h2>
  </div>
</template>

<script>
import HelloVuex from './components/HelloVuex'

export default {
  name: 'App',
  data(){
    return{
      message:'我是app组件',
      counter:0
    }
  },
  components:{
    HelloVuex
  },
  methods:{
    addCounter(){
      //在这个方法中提交mutation,使用commit方法提交
      this.$store.commit('increment');//increment
    },
    jianCounter(){
      //其实就是通过commit来提交一个函数,这个函数恰恰又是在修改state的内容
      this.$store.commit('decrement');

    },
  }
}
</script>

<style>

</style>

案例2,在以上基础上
myindex.js

import Vue from 'vue'
import Vuex from 'vuex'

//1、安装插件
Vue.use(Vuex);

//2、创建vuex对象
const store = new Vuex.Store({
  //在store里面放置的对象
  //状态
  state: {
    counter: 1000,
    students: [
      { id: 110, name: 'zhangsan', age: 34 },
      { id: 111, name: 'lisi', age: 14 },
      { id: 112, name: 'wangwer', age: 13 },
      { id: 113, name: 'dingyi', age: 14 },
      { id: 114, name: 'masan', age: 25 },
      { id: 115, name: 'zhaoliu', age: 33 }
  
    ]
  },
  mutations: {
    //可以定义方法,方法会有一个默认的state参数
    increment() { 
      this.state.counter++
    },
    decrement() { 
      this.state.counter--
    }

  },
  actions: {

  },
  getters: {
    //这里也有一个默认的state参数
    powerCount(state) { 
      return state.counter*state.counter
    },
    //获取成年学生对象,可以将默认state参数写在参数列表里
    adultStudent(state){
      //使用fliter函数进行筛选
      return state.students.filter(s=>{
        //使用箭头函数进行遍历筛选
        return s.age>=18;
      });
    },
    //获取成年学生的数量
    adultStudentLength(state,getters) { //这里state看似没用上,但在调用adultStudent的时候用到了
      return getters.adultStudent.length;
    },
    //用参数把年龄传入进来
    moreAgeStu(state) {
      //返回一个函数,以方便再app.vue中去调用参数
      return function (age) { 
        return state.students.filter(s => s.age > age);
      }

    }

  },
  modules: {

  }
})

//3、导出store对象
export default store;

HelloVuex.js

<template>
  <div>
    <h4>{{$store.state.counter}}</h4>
    <h4>{{$store.getters.powerCount}}</h4>
    <h4>{{$store.getters.adultStudent}}</h4>
    <h4>{{$store.getters.adultStudentLength}}</h4>
    <h4>{{$store.getters.moreAgeStu(30)}}</h4>

  </div>
</template>
<script>
export default {
  name:'HelloVuex',
 
}
</script>
<style scoped>

</style>

App.vue

<template>
  <div id="app">
    <h2>{{message}}</h2>
    <h2 >{{$store.state.counter}}</h2>
    <button @click="addCounter">+</button>
    <button @click="jianCounter">-</button>
    <hello-vuex></hello-vuex>
    <h4 >App内容:演示getters相关信息</h4>
    <h4>{{$store.getters.powerCount}}</h4>
    <h4>{{$store.getters.adultStudent}}</h4>
    <h4>{{$store.getters.adultStudentLength}}</h4>
    <h4>{{$store.getters.moreAgeStu(30)}}</h4>
    
  </div>
</template>

<script>
import HelloVuex from './components/HelloVuex'

export default {
  name: 'App',
  data(){
    return{
      message:'我是app组件',
      counter:0
    }
  },
  computed:{
    
  },
  components:{
    HelloVuex
  },
  methods:{
    addCounter(){
      //在这个方法中提交mutation,使用commit方法提交
      this.$store.commit('increment');//increment
    },
    jianCounter(){
      //其实就是通过commit来提交一个函数,这个函数恰恰又是在修改state的内容
      this.$store.commit('decrement');

    },
  }
}
</script>

<style>

</style>
7、mutation状态更新

Vuex的store状态的更新唯一方式就是:提交mutation

  • 1、mutation主要包含两个部分

1、事件类型(type)
2、回调函数(hander),该回调函数的第一个参数就是state

  • 2、mutation的定义方式
mutations: {
    //可以定义方法,方法会有一个默认的state参数
    increment() { 
      this.state.counter++
    },
    decrement() { 
      this.state.counter--
    }

  },
  • 3、通过mutation更新(state)状态
methods:{
    addCounter(){
      //在这个方法中提交mutation,使用commit方法提交
      this.$store.commit('increment');//increment
    },
    jianCounter(){
      //其实就是通过commit来提交一个函数,这个函数恰恰又是在修改state的内容
      this.$store.commit('decrement');

    },
  }
  • 4、通过mutation更新(state)状态时传递参数

这个被传递进来的参数被称为mutation的载荷(Payload)

incrementCount(state,counte) { 
        state.counter+=counte
    }

完整代码muindex.js

import Vue from 'vue'
import Vuex from 'vuex'

//1、安装插件
Vue.use(Vuex);

//2、创建vuex对象
const store = new Vuex.Store({
  //在store里面放置的对象
  //状态
  state: {
    counter: 1000,
    students: [
      { id: 110, name: 'zhangsan', age: 34 },
      { id: 111, name: 'lisi', age: 14 },
      { id: 112, name: 'wangwer', age: 13 },
      { id: 113, name: 'dingyi', age: 14 },
      { id: 114, name: 'masan', age: 25 },
      { id: 115, name: 'zhaoliu', age: 33 }
  
    ]
  },
  mutations: {
    //可以定义方法,方法会有一个默认的state参数
    increment() { 
      this.state.counter++
    },
    decrement() { 
      this.state.counter--
    },
    incrementCount(state,counte) { 
        state.counter+=counte
    }

  },
  actions: {

  },
  getters: {
    //这里也有一个默认的state参数
    powerCount(state) { 
      return state.counter*state.counter
    },
    //获取成年学生对象,可以将默认state参数写在参数列表里
    adultStudent(state){
      //使用fliter函数进行筛选
      return state.students.filter(s=>{
        //使用箭头函数进行遍历筛选
        return s.age>=18;
      });
    },
    //获取成年学生的数量
    adultStudentLength(state,getters) { //这里state看似没用上,但在调用adultStudent的时候用到了
      return getters.adultStudent.length;
    },
    //用参数把年龄传入进来
    moreAgeStu(state) {
      //返回一个函数,以方便再app.vue中去调用参数
      return function (age) { 
        return state.students.filter(s => s.age > age);
      }

    }

  },
  modules: {

  }
})

//3、导出store对象
export default store;

在app.vue里面定义
template内部为

<button @click="addCoun(5)">+5</button>

script部分(methods对象内)为

 methods:{
    addCounter(){
      //在这个方法中提交mutation,使用commit方法提交
      this.$store.commit('increment');//increment
    },
    jianCounter(){
      //其实就是通过commit来提交一个函数,这个函数恰恰又是在修改state的内容
      this.$store.commit('decrement');

    },
    addCoun(counte){
      this.$store.commit('incrementCount',counte);
    }
  }

完整代码为:

<template>
  <div id="app">
    <h2>{{message}}</h2>
    <h2 >{{$store.state.counter}}</h2>
    <button @click="addCounter">+</button>
    <button @click="jianCounter">-</button>
    <button @click="addCoun(5)">+5</button>
    <hello-vuex></hello-vuex>
    <h4 >App内容:演示getters相关信息</h4>
    <h4>{{$store.getters.powerCount}}</h4>
    <h4>{{$store.getters.adultStudent}}</h4>
    <h4>{{$store.getters.adultStudentLength}}</h4>
    <h4>{{$store.getters.moreAgeStu(30)}}</h4>
    
  </div>
</template>

<script>
import HelloVuex from './components/HelloVuex'

export default {
  name: 'App',
  data(){
    return{
      message:'我是app组件',
      counter:0
    }
  },
  computed:{
    
  },
  components:{
    HelloVuex
  },
  methods:{
    addCounter(){
      //在这个方法中提交mutation,使用commit方法提交
      this.$store.commit('increment');//increment
    },
    jianCounter(){
      //其实就是通过commit来提交一个函数,这个函数恰恰又是在修改state的内容
      this.$store.commit('decrement');

    },
    addCoun(counte){
      this.$store.commit('incrementCount',counte);
    }
  }
}
</script>

<style>

</style>
  • 5、通过mutation更新(state)状态时传递多个参数
    如果添加多个参数,可以先将多个参数打包成一个对象再传入
    app.vue文件
<button @click="addstudent">添加学生</button>
//添加多个参数(多个参数打包成一个对象)
    addstudent(){
      const stu= { id: 116, name: 'sunqi', age: 35 };
      this.$store.commit('pushstu',stu);
    }

完整代码

<template>
  <div id="app">
    <h2>{{message}}</h2>
    <h2 >{{$store.state.counter}}</h2>
    <button @click="addCounter">+</button>
    <button @click="jianCounter">-</button>
    <button @click="addCoun(5)">+5</button>
    <button @click="addstudent">添加学生</button>
    <hello-vuex></hello-vuex>
    <h4 >App内容:演示getters相关信息</h4>
    <h4>{{$store.getters.powerCount}}</h4>
    <h4>{{$store.getters.adultStudent}}</h4>
    <h4>{{$store.getters.adultStudentLength}}</h4>
    <h4>{{$store.getters.moreAgeStu(30)}}</h4>
    
  </div>
</template>

<script>
import HelloVuex from './components/HelloVuex'

export default {
  name: 'App',
  data(){
    return{
      message:'我是app组件',
      counter:0
    }
  },
  computed:{
    
  },
  components:{
    HelloVuex
  },
  methods:{
    addCounter(){
      //在这个方法中提交mutation,使用commit方法提交
      this.$store.commit('increment');//increment
    },
    jianCounter(){
      //其实就是通过commit来提交一个函数,这个函数恰恰又是在修改state的内容
      this.$store.commit('decrement');

    },
    //添加一个参数
    addCoun(counte){
      this.$store.commit('incrementCount',counte);
    },
    //添加多个参数(多个参数打包成一个对象)
    addstudent(){
      const stu= { id: 116, name: 'sunqi', age: 35 };
      this.$store.commit('pushstu',stu);
    }
  }
}
</script>

<style>

</style>

myindex.js文件

 //更新多个参数(多个参数打包成一个对象传入)
    pushstu(state,stu) { 
      state.students.push(stu);
    }

完整代码

import Vue from 'vue'
import Vuex from 'vuex'

//1、安装插件
Vue.use(Vuex);

//2、创建vuex对象
const store = new Vuex.Store({
  //在store里面放置的对象
  //状态
  state: {
    counter: 1000,
    students: [
      { id: 110, name: 'zhangsan', age: 34 },
      { id: 111, name: 'lisi', age: 14 },
      { id: 112, name: 'wangwer', age: 13 },
      { id: 113, name: 'dingyi', age: 14 },
      { id: 114, name: 'masan', age: 25 },
      { id: 115, name: 'zhaoliu', age: 33 }
  
    ]
  },
  mutations: {
    //可以定义方法,方法会有一个默认的state参数
    increment() { 
      this.state.counter++
    },
    decrement() { 
      this.state.counter--
    },
    //传入一个参数
    incrementCount(state,counte) { 
        state.counter+=counte
    },
    //更新多个参数(多个参数打包成一个对象传入)
    pushstu(state,stu) { 
      state.students.push(stu);
    }

  },
  actions: {

  },
  getters: {
    //这里也有一个默认的state参数
    powerCount(state) { 
      return state.counter*state.counter
    },
    //获取成年学生对象,可以将默认state参数写在参数列表里
    adultStudent(state){
      //使用fliter函数进行筛选
      return state.students.filter(s=>{
        //使用箭头函数进行遍历筛选
        return s.age>=18;
      });
    },
    //获取成年学生的数量
    adultStudentLength(state,getters) { //这里state看似没用上,但在调用adultStudent的时候用到了
      return getters.adultStudent.length;
    },
    //用参数把年龄传入进来
    moreAgeStu(state) {
      //返回一个函数,以方便再app.vue中去调用参数
      return function (age) { 
        return state.students.filter(s => s.age > age);
      }

    }

  },
  modules: {

  }
})

//3、导出store对象
export default store;
8、mutation状态更新的提交风格

传统风格

//添加一个参数
    addCoun(counte){
      this.$store.commit('incrementCount',counte);
    },

包含type属性的风格
在commit参数列表里提交的是一个对象

//添加一个参数
    addCoun(counte){
      //this.$store.commit('incrementCount',counte);
      //特殊的提交风格,提交的是一个对象
      this.$store.commit({
        type:'incrementCount',
        count,//需要传递的参数,但也是作为对象传过来的
      })
    },

mutation的处理方式是将整个commit的对象作为payload使用,所以代码没有改变
在这里插入图片描述

9、mutation的响应规则

Vuex的store中的state是响应式的,当state中的数据发生改变时,Vue组件会自动更新

如果想要自动响应,就必须遵守vuex的规则

  • 1、提前在stroe中初始化好所需的属性

在store中的state里的info中添加好这些属性(name,age,height等),如果添加属性,则无法即时响应,因为无法监听没有被实现设定好的属性。

 //在state里的对象都可以即时响应
    info: {
      name: 'zhangsan',
      age: 33,
      height:1.47
    }
  • 2、当给state中的对象添加新属性时,使用下面的方式进行,这样新添加的属性就可以成为即时响应的
    方法1:
    使用Vue.set(obj,‘newProp’’,123)
    添加新的属性
//修改了info对象的值
    updateInfo(state) { 
      //state.info.name='lisi'
      //添加新的属性,添加一个address属性
      Vue.set(state.info, 'address','beijing');

    }

删除新的属性

//修改了info对象的值
    updateInfo(state) { 
      //state.info.name='lisi'
      //添加新的属性,添加一个address属性
      //Vue.set(state.info, 'address', 'beijing');
      //删除一个属性
      Vue.delete(state.info, 'age');
    }

方法2:
使用新对象给旧对象重新赋值

完整代码
myindex.vue

import Vue from 'vue'
import Vuex from 'vuex'

//1、安装插件
Vue.use(Vuex);

//2、创建vuex对象
const store = new Vuex.Store({
  //在store里面放置的对象
  //状态
  state: {
    counter: 1000,
    students: [
      { id: 110, name: 'zhangsan', age: 34 },
      { id: 111, name: 'lisi', age: 14 },
      { id: 112, name: 'wangwer', age: 13 },
      { id: 113, name: 'dingyi', age: 14 },
      { id: 114, name: 'masan', age: 25 },
      { id: 115, name: 'zhaoliu', age: 33 }
  
    ],
    //在state里的对象都可以即时响应
    info: {
      name: 'zhangsan',
      age: 33,
      height:1.47
    }
  },
  mutations: {
    //可以定义方法,方法会有一个默认的state参数
    increment() { 
      this.state.counter++
    },
    decrement() { 
      this.state.counter--
    },
    //传入一个参数
    incrementCount(state,counte) { 
        state.counter+=counte
    },
    //更新多个参数(多个参数打包成一个对象传入)
    pushstu(state,stu) { 
      state.students.push(stu);
    },
    //修改了info对象的值
    updateInfo(state) { 
      //state.info.name='lisi'
      //添加新的属性,添加一个address属性
      //Vue.set(state.info, 'address', 'beijing');
      //删除一个属性
      Vue.delete(state.info, 'age');
    }

  },
  actions: {

  },
  getters: {
    //这里也有一个默认的state参数
    powerCount(state) { 
      return state.counter*state.counter
    },
    //获取成年学生对象,可以将默认state参数写在参数列表里
    adultStudent(state){
      //使用fliter函数进行筛选
      return state.students.filter(s=>{
        //使用箭头函数进行遍历筛选
        return s.age>=18;
      });
    },
    //获取成年学生的数量
    adultStudentLength(state,getters) { //这里state看似没用上,但在调用adultStudent的时候用到了
      return getters.adultStudent.length;
    },
    //用参数把年龄传入进来
    moreAgeStu(state) {
      //返回一个函数,以方便再app.vue中去调用参数
      return function (age) { 
        return state.students.filter(s => s.age > age);
      }

    }

  },
  modules: {

  }
})

//3、导出store对象
export default store;

App.vue

<template>
  <div id="app">
    <h2>{{message}}</h2>
    <h2 >{{$store.state.counter}}</h2>
    <button @click="addCounter">+</button>
    <button @click="jianCounter">-</button>
    <button @click="addCoun(5)">+5</button>
    <button @click="addstudent">添加学生</button>
    <hello-vuex></hello-vuex>
    <h4 >App内容:演示getters相关信息</h4>
    <h4>{{$store.getters.powerCount}}</h4>
    <h4>{{$store.getters.adultStudent}}</h4>
    <h4>{{$store.getters.adultStudentLength}}</h4>
    <h4>{{$store.getters.moreAgeStu(30)}}</h4>
    <h4>-----info对象的内容是否是响应式的------</h4>
    <h4>{{$store.state.info}}</h4>
    <button @click="updateInfo">修改信息</button>
    
  </div>
</template>

<script>
import HelloVuex from './components/HelloVuex'

export default {
  name: 'App',
  data(){
    return{
      message:'我是app组件',
      counter:0
    }
  },
  computed:{
    
  },
  components:{
    HelloVuex
  },
  methods:{
    addCounter(){
      //在这个方法中提交mutation,使用commit方法提交
      this.$store.commit('increment');//increment
    },
    jianCounter(){
      //其实就是通过commit来提交一个函数,这个函数恰恰又是在修改state的内容
      this.$store.commit('decrement');

    },
    //添加一个参数
    addCoun(counte){
      //this.$store.commit('incrementCount',counte);
      //特殊的提交风格,提交的是一个对象
      this.$store.commit({
        type:'incrementCount',
        count,//需要传递的参数,但也是作为对象传过来的
      })
    },
    //添加多个参数(多个参数打包成一个对象)
    addstudent(){
      const stu= { id: 116, name: 'sunqi', age: 35 };
      this.$store.commit('pushstu',stu);
    },
    updateInfo(){
      this.$store.commit('updateInfo')
    }
  }
}
</script>

<style>

</style>
10、mutation的类型常量

对一些函数名,字符串等取一个常量名(别名)

11、mutation的同步函数

通常情况下,Vuex要求我们mutation中的方法必须是同步方法

主要是因为我们使用devtools时,devtools可以捕捉到mutation的快照。

但是如果是异步操作,那么devtools将不能很好的追踪这个操作说明时候会被完成

因此,不要在mutation中进行异步操作,而是用action类来替代mutation进行异步操作

在Vue组件中, 如果我们调用action中的方法, 那么就需要使用dispatch进行分发
在这里插入图片描述

在myindex.js中修改

actions: {
    //有个默认参数context(上下文),context实际就是不同情境下不同含义的内容
    aupdateinfo(context,payload) { //也可以同步传参
      //模拟异步操作
      setTimeout(() => {
        //提交原有在mutation中就有的方法
        context.commit('updateInfo');
        console.log(payload);
      }, 1000);
    }

App.vue中修改
component到action需要使用dispath来过渡及传递信息

 updateInfo(){
      //由于在myindex里面是通过action来commit的,这里要改成dispath完成componet到action的过度
      this.$store.dispatch('aupdateinfo','我是payload');//参数是action里面定义的方法
    }

最终代码:
myindex.js

import Vue from 'vue'
import Vuex from 'vuex'

//1、安装插件
Vue.use(Vuex);

//2、创建vuex对象
const store = new Vuex.Store({
  //在store里面放置的对象
  //状态
  state: {
    counter: 1000,
    students: [
      { id: 110, name: 'zhangsan', age: 34 },
      { id: 111, name: 'lisi', age: 14 },
      { id: 112, name: 'wangwer', age: 13 },
      { id: 113, name: 'dingyi', age: 14 },
      { id: 114, name: 'masan', age: 25 },
      { id: 115, name: 'zhaoliu', age: 33 }
  
    ],
    //在state里的对象都可以即时响应
    info: {
      name: 'zhangsan',
      age: 33,
      height:1.47
    }
  },
  mutations: {
    //可以定义方法,方法会有一个默认的state参数
    increment() { 
      this.state.counter++
    },
    decrement() { 
      this.state.counter--
    },
    //传入一个参数
    incrementCount(state,counte) { 
        state.counter+=counte
    },
    //更新多个参数(多个参数打包成一个对象传入)
    pushstu(state,stu) { 
      state.students.push(stu);
    },
    //修改了info对象的值
    updateInfo(state) {
      state.info.name = 'lisi';
    }

  },
  actions: {
    //有个默认参数context(上下文),context实际就是不同情境下不同含义的内容
    aupdateinfo(context,payload) { //也可以同步传参
      //模拟异步操作
      setTimeout(() => {
        //提交原有在mutation中就有的方法
        context.commit('updateInfo');
        console.log(payload);
      }, 1000);
    }


  },
  getters: {
    //这里也有一个默认的state参数
    powerCount(state) { 
      return state.counter*state.counter
    },
    //获取成年学生对象,可以将默认state参数写在参数列表里
    adultStudent(state){
      //使用fliter函数进行筛选
      return state.students.filter(s=>{
        //使用箭头函数进行遍历筛选
        return s.age>=18;
      });
    },
    //获取成年学生的数量
    adultStudentLength(state,getters) { //这里state看似没用上,但在调用adultStudent的时候用到了
      return getters.adultStudent.length;
    },
    //用参数把年龄传入进来
    moreAgeStu(state) {
      //返回一个函数,以方便再app.vue中去调用参数
      return function (age) { 
        return state.students.filter(s => s.age > age);
      }

    }

  },
  modules: {

  }
})

//3、导出store对象
export default store;

App.vue

<template>
  <div id="app">
    <h2>{{message}}</h2>
    <h2 >{{$store.state.counter}}</h2>
    <button @click="addCounter">+</button>
    <button @click="jianCounter">-</button>
    <button @click="addCoun(5)">+5</button>
    <button @click="addstudent">添加学生</button>
    <hello-vuex></hello-vuex>
    <h4 >App内容:演示getters相关信息</h4>
    <h4>{{$store.getters.powerCount}}</h4>
    <h4>{{$store.getters.adultStudent}}</h4>
    <h4>{{$store.getters.adultStudentLength}}</h4>
    <h4>{{$store.getters.moreAgeStu(30)}}</h4>
    <h4>-----info对象的内容是否是响应式的------</h4>
    <h4>{{$store.state.info}}</h4>
    <button @click="updateInfo">修改信息</button>
    
  </div>
</template>

<script>
import HelloVuex from './components/HelloVuex'

export default {
  name: 'App',
  data(){
    return{
      message:'我是app组件',
      counter:0
    }
  },
  computed:{
    
  },
  components:{
    HelloVuex
  },
  methods:{
    addCounter(){
      //在这个方法中提交mutation,使用commit方法提交
      this.$store.commit('increment');//increment
    },
    jianCounter(){
      //其实就是通过commit来提交一个函数,这个函数恰恰又是在修改state的内容
      this.$store.commit('decrement');

    },
    //添加一个参数
    addCoun(counte){
      //this.$store.commit('incrementCount',counte);
      //特殊的提交风格,提交的是一个对象
      this.$store.commit({
        type:'incrementCount',
        count,//需要传递的参数,但也是作为对象传过来的
      })
    },
    //添加多个参数(多个参数打包成一个对象)
    addstudent(){
      const stu= { id: 116, name: 'sunqi', age: 35 };
      this.$store.commit('pushstu',stu);
    },
    updateInfo(){
      //由于在myindex里面是通过action来commit的,这里要改成dispath完成componet到action的过度
      this.$store.dispatch('aupdateinfo','我是payload');//参数是action里面定义的方法
    }
  }
}
</script>

<style>

</style>
12、Modules模块

就是在store里面分模块,然后在不同的模块里面再定义state,mutations,actions,getters等等

  • 1、为什么要用模块

Vue使用单一状态树,那么也意味着很多状态都会交给Vuex来管理.
当应用变得非常复杂时,store对象就有可能变得相当臃肿.
为了解决这个问题, Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutations、actions、getters等

modules: {
    modulesA: {
      state: {},
      mutations: {},
      actions: {},
      getters:{}
    },
    modulesB: {
      state: {},
      mutations: {},
      actions: {},
      getters:{}
    }
  }
13、获取不同模块的数据
  • 1、myindex.js里面编写模块数据

和写一般的state没有区别,但是注意模块名称

modules: {
    modulesA: {
      state: {
        name:'zhangsan '
      },
      mutations: {},
      actions: {},
      getters:{}
    },
    modulesB: {
      state: {},
      mutations: {},
      actions: {},
      getters:{}
    }
  }
  • 2、app.vue里面

模板内添加

//是state后面加模块名+数据名,不是模块state再数据名
<h2>{{$store.state.modulesA.name}}</h2>
14、不同模块使用mutation
  • 1、 myindex.js编辑模块,添加一个mutations方法
 modules: {
    modulesA: {
      state: {
        name:'zhangsan '
      },
      mutations: {
        updteName(state,payload) { 
          state.name = payload;
        }
      },
      actions: {},
      getters:{}
    },
  • 2、 app.vue添加template模块代码
 <h2>{{$store.state.modulesA.name}}</h2>
<button @click="modifyname">修改名字</button>
  • 3、 app.vue脚本内添加一个methods来commit这个方法
    commit是不关心commit的方法是在哪个模块的(也就是不需要写模块名)
 modifyname(){
      this.$store.commit('updteName','zhaoliu')
    }
15、不同模块使用mutation
  • 1、在myindex.js模块内添加
getters: {
        fullname(sate) { 
          return state.name+' mrs'
        }
      }

模板文件中填写响应数据引用
getters是不关心getters的方法是在哪个模块的(也就是不需要写模块名)

  • 2、在myindex.js模块内添加
<h4>{{$store.getters.fullname}}</h4>
16、不同模块使用actions处理异步操作

1、myindex.js中填写action的异步操作方法

actions: {
        aupdateName(context) { 
          setTimeout(() => {
            context.commit('updteName','wangwu');//commit自己模块的元素
          }, 1000);
        }
      },

2、app.vue中填写处理方法
模板中填写

<button @click="asyncUpdateName">异步修改名字</button>

脚本中methods方法

asyncUpdateName(){
      this.$store.dispatch('aupdateName')
    }
17、项目目录结构

当我们的Vuex帮助我们管理过多的内容时, 好的项目结构可以让我们的代码更加清晰.
核心思想就是抽离成文件,然后导入该文件,说着容易,但是做起来好像也没那么简单
在这里插入图片描述
其实应该抽成这样的
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值