1

Vuex 是什么?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理器,采用 集中式存储 管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vue核心概念

State

Vuex store实例的根状态对象,用于定义共享的状态变量。

Getter

读取器,外部程序通过它获取变量的具体值,或者在取值前做一些计算(可以认为是store的计算属性)

Mutation

修改器,它只用于修改state中定义的状态变量。

Action

动作,向store发出调用通知,执行本地或者远端的某一个操作(可以理解为store的methods)

Module

vuex在vue-cli中的应用

第一步:npm下载vuex资源包:

npm install vuex -S

第二步:在 src 下创建文件夹,在 src 下创建 store.js ,官方推荐项目结构
clipboard.png

store.js文件

import Vue from 'vue'
import Vuex from 'vuex'
import * as getters from './store/getters' // 导入响应的模块,*相当于引入了这个组件下所有导出的事例
import * as actions from './store/actions'
import * as mutations from './store/mutations'
Vue.use(Vuex)

// 首先声明一个需要全局维护的状态 state,比如 titelName
const state = {
  titelName: '小A的大标题' // 默认值
  // id: xxx  如果还有全局状态也可以在这里添加
  // name:xxx
}
export default new Vuex.Store({
  strict: process.env.NODE_ENV !== 'production', //在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。不要在发布环境下启用严格模式以避免性能损失!
  state,    // 共同维护的一个状态,state里面可以是很多个全局状态
  getters,  // 获取数据并渲染
  actions,  // 数据的异步操作
  mutations  // 处理数据的唯一途径,state的改变或赋值只能在这里
})

getter.js 文件

// 获取最终的状态信息
export const titelName = state => state.titelName

actions.js 文件

// 给action注册事件处理函数。当这个函数被触发时候,将状态提交到mutations中处理
export function modifyAName({ commit }, name) { // commit 提交;name即为点击后传递过来的参数,此时是 'A餐馆'
    return commit('modifyAName', name)
}
// export const modifyAName = ({commit},name) => commit('modifyAName', name)
export const modifyBName = ({ commit }, name) => commit('modifyBName', name)

mutations.js 文件

// 提交 mutations是更改Vuex状态的唯一合法方法
export const modifyAName = (state, name) => {
    state.titelName = name // 把方法传递过来的参数,赋值给state中的titelName
}
export const modifyBName = (state, name) => {
    state.titelName = name
}    

router.js 文件

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import componentA from './components/componentA.vue'
import componentB from './components/componentB.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/about',
      name: 'about',
      // route level code-splitting
      // this generates a separate chunk (about.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
    },
    {
      path: '/componentA',
      name: 'componentA',
      component: componentA
    },
    {
      path: '/componentB',
      name: 'componentB',
      component: componentB
    },
  ]
})

componentA.vue 文件

   <template>
      <div>
        <span>A页面名字</span>
        <input type="text" name id v-model="titelName" @keydown="modifyAName(titelName)">
        <button @click="modifyAName('ssds')">改标题</button>
        <button @click="jump()">调到B页面</button>
      </div>
    </template>
    
    <script>
    // import { mapActions, mapGetters } from "vuex";
    import { mapActions } from "vuex";
    export default {
      data() {
        return {};
      },
      methods: {
        ...mapActions(['modifyAName']), // 相当于this.$store.dispatch('modifyName'),提交这个方法
        jump() {
          this.$router.push("componentB");
        }
      },
      computed: {
        //注意 v-model v-if
        // ...mapGetters(["titelName"])
        titelName: {
          get() {
            return this.$store.state.titelName;
          },
          set(val) {
            console.log(val);
            this.$store.commit('modifyAName', val);
            // this.$store.dispatch('modifyAName');
            console.log(this.$store.state.titelName);
          }
        }
      }
    };
    </script>
    
    <style scoped>
    </style>
    

componentB.vue 文件

<template>
  <div>
    <span>B页面名字</span>
    <input type="text" name id v-model="titelName" @keydown="modifyBName(titelName)">
    <button @click="jump()">调到A页面</button>
  </div>
</template>

<script>
// import { mapActions, mapGetters } from "vuex";
import { mapActions } from "vuex";
export default {
  data() {
    return {};
  },
  methods: {
    ...mapActions(
      //
      ["modifyBName"]
    ),
    jump() {
      this.$router.push("componentA");
    }
  },
  computed: {
    // ...mapGetters(["titelName"])
    titelName: {
      get: function() {
        return this.$store.state.titelName;
      },
      set: function(val) {
        this.$store.commit("modifyBName", val);
      }
    }
  }
};
</script>

<style scoped>
</style>

//第三步:在 src/main.js 中引入    
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({  
  router,
  store,
  render: h => h(App)
}).$mount('#app')

如何在组件中去使用vuex的值和方法

直接获取、修改

//state
this.$store.state.count
//getter
this.$store.getters.count
//调用 action 修改 state 值,不带参数
this.$store.dispatch('increment');
//调用 action 修改 state 值,带参数
this.$store.dispatch('increment',{value :123});

通过 辅助函数 获取、修改vuex

vuex提供了三种辅助函数用于获取、修改vuex:
mapState、mapGetters、mapActions
即将vuex的变量或者方法映射到vue组件this指针上。

使用state获取共享变量

<script type="text/javascript">
import { mapState } from 'vuex'
export default{
    computed : {
        ...mapState([
            'count',
            'buttonShow'
        ])
    }
}
</script>

使用getters获取共享变量,

<script type="text/javascript">
import { mapGetters } from 'vuex'
export default{
    computed : {
        ...mapGetters([
            'count',
            'buttonShow'
        ])
    }
}
</script>

使用actions修改共享变量

<script type="text/javascript">
import { mapActions } from 'vuex'
export default{
    methods : {
        ...mapActions({increment:'increment',decrement:'decrement'}),
    }
}
</script>

liuoomei
175 声望18 粉丝

走出舒适区,外面的风景格外迷人!