vuex中mapState用法解析

一、state

state是什么?

定义:state(vuex) ≈ data (vue)

vuex的state和vue的data有很多相似之处,都是用于存储一些数据,或者说状态值.这些值都将被挂载 数据和dom的双向绑定事件,也就是当你改变值的时候可以触发dom的更新.

虽然state和data有很多相似之处,但state在使用的时候一般被挂载到子组件的computed计算属性上,这样有利于state的值发生改变的时候及时响应给子组件.如果你用data去接收$store.state,当然可以接收到值,但由于这只是一个简单的赋值操作,因此state中的状态改变的时候不能被vue中的data监听到,当然你也可以通过watch $store去解决这个问题,那你可以针是一个杠精

综上所述,请用computed去接收state,如下

//state.js
let state = {
  count: 1,
  name: 'dkr',
  sex: '男',
  from: 'china'
}
export default state
<template>
  <div id="example">
    <button @click="decrement">-</button>
    {{count}}
    {{dataCount}}
    <button @click="increment">+</button>
  </div>
</template>
<script>
export default {
  data () {
    return {
      dataCount: this.$store.state.count //用data接收
    }
  },
  computed:{
    count(){
      return this.$store.state.count //用computed接收
    }
  }
  methods: {
    increment () {
      this.$store.commit('increment')
    },
    decrement () {
      this.$store.commit('decrement')
    }
  }
}
</script>

在这里插入图片描述

二、mapstate辅助函数

mapState是什么?

表面意思:mapState是state的辅助函数.这么说可能很难理解

抽象形容:mapState是state的语法糖,这么说可能你还想骂我,因为你根本不了解什么叫做语法糖,事实上我说的语法糖有自己的定义,什么是语法糖?我对语法糖的理解就是,用之前觉得,我明明已经对一种操作很熟练了,并且这种操作也不存在什么问题,为什么要用所谓的"更好的操作",用了一段时间后,真香!

实际作用:当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键

在使用mapState之前,要导入这个辅助函数

import { mapState } from 'vuex'

store.js

// store.js
/**
    vuex的核心管理对象模块:store
 */
import Vue from 'vue';
import Vuex from 'vuex';
import vuexTest from './modules/vuexTest';

Vue.use(Vuex)
// 状态对象
const state = { // 初始化状态 这里放置的状态可以被多个组件共享
    count: 1,
    count1: 1,
    count2: 2,
    count3: 3,
    name: 'daming'
};
const mutations = {};
const actions = {};
const getters = {};

export default new Vuex.Store({
    state, // 状态
    mutations, // 包含多个更新state函数的对象
    actions, // 包含多个队形事件回调函数的对象
    getters, // 包含多个getter计算属性函数的对象
    modules: { // 模块化
        vuexTest
    }
});

1、在界面或组件中不使用mapState获取vuex中state的状态

虽然将所有的状态放入Vuex,会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态,比如temp变量,hello, number作为组件的局部状态。

<!-- test.vue -->
<template>
  <div id="example">
    {{count}}
    {{name}}
    {{helloName}}
    {{addNumber}}
  </div>
</template>

<script>
export default {
  data() {
    return {
      hello: 'hello',
      number: 1,
    }
  },
  computed: {

    // 由于 Vuex 的状态存储是响应式的,所以可以使用计算属性来获得某个状态
    // 通过下面的计算属性,就可以在当前组件中访问到count,name,helloName,addNumber 在模板中我们通过大括号符号打印出来,当然这些可以在vue中使用,比如在watch中监听,在mounted中使用

    // 下面的计算属性涉及到了vuex管理的状态
    count() { // 这实际上是ES6中对象的简化写法 完整写法是 count: function { return this.$store.state.count }
      return this.$store.state.count
    },
    name() { // 这实际上是ES6中对象的简化写法 完整写法是 name: function { return this.$store.state.count }
      return this.$store.state.count
    },
    helloName: function (state) { // 为了能够使用 `this` 获取局部状态,必须使用常规函数,不能使用箭头函数
      return this.hello + this.$store.state.name
    },
    addNumber: function (state) { // 为了能够使用 `this` 获取局部状态,必须使用常规函数,不能使用箭头函数
      return this.number + this.$store.state.count
    }
    // 但有一个问题
    // 当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。比如上面的name(),count(),helloName(),显得重复,代码冗长
    // 为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键:
  },
  watch: {
     helloName(newVal,oldVal){
         console.log(newVal);
         console.log(oldVal);
     } 
  },
  mounted(){
      console.log(this.helloName);
  }
}
</script>

2、在组件、界面中使用mapState获取vuex中state的数据

<!-- test.vue -->
<template>
  <div id="example">
    {{count}}
    {{count1}}
    {{repeatCount}}
    {{count3}}
    {{name}}
    {{helloName}}
    {{addNumber}}
  </div>
</template>

<script>
export default {
  data() {
    return {
      hello: 'hello',
      number: 1,
      count2: 2
    }
  },
  computed: {
    /**
     * 数组形式
     * 当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。
     * */
    ...mapState(["count", "name"]),


    /**
     * 对象形式
     */
    ...mapState({
      count, // 这种就是count:"count", 的简写
      count1: "count1",
      repeatCount: "count2", // 当组件中与vuex中的字符已经出现重复时,使用 repeatCount 来映射 store.state.count2
      count3: (state) => { // 映射 count3 为 store.state.conut3的值
        return state.count3
      },
      helloName: function (state) { // 为了能够使用 `this` 获取局部状态,必须使用常规函数,不能使用箭头函数
        return this.hello + state.name
      },
      addNumber: function (state) { // 为了能够使用 `this` 获取局部状态,必须使用常规函数,不能使用箭头函数
        return this.number + state.count
      }
    })
  },
  watch: {
    helloName(newVal, oldVal) {
      console.log(newVal);
      console.log(oldVal);
    }
  },
  mounted() {
    console.log(this.helloName);
  }
}
</script>

3、modules的vuexTest模块中state数据

/**
 * vuexTest.js
 * modules 中的数据
 */
export default {
    namespaced: true,
    state: {
        moduleVal: 1,
        moduleName: "战战兢兢"
    },
    getters: {
    },
    mutations: {
    },
    actions: {
    }
}

4、在界面或组件中不使用mapState获取模块modules vuexTest中state的状态

<!-- module test.vue -->
<template>
  <div id="example">
    {{moduleVal}}
    {{moduleName}}
    {{moduleNameOther}}
  </div>
</template>

<script>
export default {
  data() {
    return {
      hello: 'hello',
      number: 1,
    }
  },
  computed: {
    moduleVal(){
        return this.$store.state.vuexTest.moduleVal
    },
    moduleName(){
        return this.$store.state.vuexTest.moduleVal
    },
    moduleNameOther(){
        // 当组件中与vuex中的字符已经出现重复时,使用 moduleNameOther 来映射 store.state.vuexTest.moduleName
        return this.$store.state.vuexTest.moduleVal 
    },
    
  },
  watch: {
    helloName(newVal, oldVal) {
      console.log(newVal);
      console.log(oldVal);
    }
  },
  mounted() {
    console.log(this.addNumber);
  }
}
</script>

5、在界面或组件中使用mapState获取模块modules vuexTest中state的状态

<!-- module test.vue -->
<template>
  <div id="example">
    {{moduleVal}}
    {{moduleName}}
    {{moduleNameOther}}
  </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
  data() {
    return {
      hello: 'hello',
      number: 1,
    }
  },
  computed: {
    /**
     * 数组形式
     * 当映射的计算属性的名称与 与模块中vuexTest中state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组,
     * */
    ...mapState("vuexTest", ["moduleVal", "moduleName"]),
    // "vuexTest" 指向模块vuexTest,"moduleVal"表示store.vuexTest.moduleVal


    /**
     * 对象形式
     */
    // 第一种对象方式
    ...mapState({
      moduleVal: "vuexTest/moduleVal",
      moduleNameOther: "vuexTest/moduleName" // 表示 moduleNameOther 映射到vuexTest模块中moduleName
    }),

    ...mapState("vuexTest", {
      moduleVal, // 这种就是moduleVal:"moduleVal", 的简写
      moduleName: "moduleName",
      moduleNameOther: "moduleName", // 当组件中与vuex中的字符已经出现重复时,使用 moduleNameOther 来映射 store.state.vuexTest.moduleName
      moduleVal: (state) => { // 映射 moduleVal 为 store.state.vuexTest.moduleVal的值
        return state.moduleVal
      },
      helloName: function (state) { // 为了能够使用 `this` 获取局部状态,必须使用常规函数,不能使用箭头函数
        return this.hello + state.moduleName
      },
      addNumber(state) { // 为了能够使用 `this` 获取局部状态,必须使用常规函数,不能使用箭头函数
        return this.number + state.moduleVal
      }
    })
  },
  watch: {
    helloName(newVal, oldVal) {
      console.log(newVal);
      console.log(oldVal);
    }
  },
  mounted() {
    console.log(this.addNumber);
  }
}
</script>

三、求关注

求关注啊!!!

你可能感兴趣的:(VUE,javascript,vue.js,前端)