vuex学习笔记

vuex

vuex是什么?Vuex是一个专为Vue.js应用程序开发的状态管理模式,其工作模式如图所示。刚开始这张图可能很难看懂,但是理解完vuex的五大核心概念(state,getters,mutations,actions,modules)以后,你应该会有自己的理解。

vuex使用需要挂载到vue实例上,这样就可以在所有组件中使用这些数据,所以我们将所有需要共享的data,使用vuex来统一管理。一般都将src下面的store文件夹中的index.js作为入口文件(文件夹及文件名自定义),然后在main.js中导入store对象。

每个应用将仅仅包含一个store实例。在根组件注册时,store实例时会被注入到根组件下面的所有组件。所有子组件都可以通过this.$store访问到。


import Vue from 'vue'
import App from './App'
import router from './router'

//sotre
import store from "./store";

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

State

可以看作为data中的属性,State中所有的属性都会被加到响应式系统中。即当监听到了属性的变化,就会通知所有用到这个属性的界面进行刷新。

我们在store文件夹下创建一个modules文件夹用来存放各个不同的模块,创建一个test文件夹及test.js用来测试。

test.js


const state = {
  message:"Hello VUEX!"
};
export default {
  state
};

修改index.js入口文件

index.js


import Vue from 'vue';
import Vuex from 'vuex';
import test from './modules/test/test';

Vue.use(Vuex);
export default new Vuex.Store({
  modules: {
    test
  }
});


添加完成后就可以在vue中调用

App.vue


<template>
  <div id="app">
    <img src="./assets/logo.png">
    <div>{{$store.state.test.message}}</div>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

并可以再调试工具中看到相应变量

Getters

有时候我们需要从state派生出来一些其他状态,类似于它的计算属性。

如我们需要将state.message字符串翻转的功能,我们无需在很多地方复制这个函数,也无需抽取到一个公共函数中然后在多处导入。我们只需要定义一个getter。然后就和计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

test.js


const state = {
  message: "Hello VUEX!"
};

const getters = {
  reversedMessage: state => {
    return state.message.split('').reverse().join('')
  }
};


export default {
  state,
  getters
};


App.vue -> template


<template>
  <div id="app">
    <img src="./assets/logo.png">
    <div>{{$store.state.test.message}}</div>
    <div>{{$store.getters.reversedMessage}}</div>
  </div>
</template>

Mutations

提交Mutation是更改store中状态的唯一方式。使用store.commit提交的时候可以传入额外的参数,称为mutation的载荷(payload)。
Mutation 必须是同步函数。当是异步函数的时候,当mutation触发了,回调函数可能还没被调用,所以在回调函数中的改变将无法追踪。

test.js

  • 添加一个Mutation用来改变message的值。

const state = {
  message: "Hello VUEX!"
};

const getters = {
  reversedMessage: state => {
    return state.message.split('').reverse().join('')
  }
};

const mutations = {
  changeMessage: (state, s = "") => {
    state.message += s
  }
};

export default {
  state,
  getters,
  mutations
};


App.vue -> template


<template>
  <div id="app">
    <img src="./assets/logo.png">
    <div>{{$store.state.test.message}}</div>
    <div>{{$store.getters.reversedMessage}}</div>
    <div>
      <button v-on:click="handleClick('Hello!')">Say Hello!</button>
    </div>
  </div>
</template>

App.vue -> script


<script>
  export default {
    name: 'App',
    methods: {
      handleClick(s) {
        this.$store.commit('changeMessage', s);
      }
    }
  }
</script>

  • 点击一次按钮后

Actions

如果处理异步操作就需要用到Action。Action不同于mutation,它提交的是mutation,而不是直接改变状态。

test.js


const state = {
  message: "Hello VUEX!"
};

const getters = {
  reversedMessage: state => {
    return state.message.split('').reverse().join('')
  }
};

const mutations = {
  changeMessage: (state, s = "") => {
    state.message += s
  }
};

const actions = {
  actionsChangeMessage: (context, s = "") => {
    context.commit('changeMessage',s)
  }
}

export default {
  state,
  getters,
  mutations,
  actions
};


App.vue -> template


<template>
  <div id="app">
    <img src="./assets/logo.png">
    <div>{{$store.state.test.message}}</div>
    <div>{{$store.getters.reversedMessage}}</div>
    <div>
      <button v-on:click="handleClick('Hello!')">Say Hello!</button>
      <button v-on:click="handleActionsClick('Hi!')">Say Hi!</button>
    </div>
  </div>
</template>

App.vue -> script


<script>
  export default {
    name: 'App',
    methods: {
      handleClick(s) {
        this.$store.commit('changeMessage', s);
      },
      handleActionsClick(s) {
        this.$store.dispatch('actionsChangeMessage', s);
      }
    }
  }
</script>

因为Action不是直接更改状态,而是提交mutation。所以我们就可以在Action内部执行异步操作。


const actions = {
  actionsChangeMessage: (context, s = "") => {
    
    setTimeout(() => {
      context.commit('changeMessage',s)
    }, 1000)    

  }
}

  • 1s后触发

Modules

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter。

就如我们上面的module目录下的test文件夹,就可以当做一个子模块。

在vuex的入口文件配置如下即可:


export default new Vuex.Store({
  modules: {
    test:test
    //, b: moduleB
  }
});

辅助函数

vuex提供了辅助函数mapState、mapGetters、mapMutations、mapActions。将vuex.store中的属性映射到vue实例身上,这样就可以在vue实例中直接访问vuex.store中的属性。

mapState,mapGetters:将属性映射到computer上
mapMutations、mapActions:将属性映射到methods上

对应的写法改为:

App.vue:


<template>
  <div id="app">
    <img src="./assets/logo.png">
    <div>{{message}}</div>
    <div>{{reversed}}</div>
    <div>
      <button v-on:click="change('Hello!')">Say Hello!</button>
      <button v-on:click="actionsChange('Hi!')">Say Hi!</button>
    </div>
  </div>
</template>

<script>
  import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'

  export default {
    name: 'App',
    computed: {
      ...mapState({
        message: state => state.test.message
      }),
      ...mapGetters({
        reversed: 'reversedMessage'
      })
    },
    methods: {
      ...mapMutations({
        change: 'changeMessage'
      }),
    ...mapActions({
          actionsChange: 'actionsChangeMessage'
        })
    }
  }
</script>

四个辅助函数的写法均有以下两种形式
...mapActions(['method1', 'method2' ]),
...mapActions({m1: 'method1',m2: 'method2', })

posted @ 2021-04-27 20:03  可爱的黑精灵  阅读(73)  评论(0编辑  收藏  举报