Vue.js--Vuex使用详解

在这里插入图片描述

Vuex

Vuex是一个专门为Vue.js应用程序开发的状态管理模式。

  • 它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
  • Vuex也集成到Vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试、状态快照导入导出等高级调试功能。

使用

安装Vuex:

npm install --save vuex

在src下新建store文件夹,在其中新建index.js作为Vuex的配置文件:

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

//安装插件
Vue.use(Vuex)

//创建对象

const store = new Vuex.Store({
   
})

//导出
export default store

在main.js中引入注册:

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

Vue.config.productionTip = false

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

仓库store包含了应用的数据(状态)和操作过程。Vuex里的数据都是响应式的,任何组件使用同一个store的数据时,只要store的数据变化,对应的组件也会立即更新。

数据保存在Vuex选项的state 字段内,比如要实现一个计数器,定义一个数据count,初始值为0:

const store = new Vuex.Store({
    state: {
        counter: 1000
    }
})

在App.vue中使用:

<template>
  <div id="app">
    <h2>App</h2>
    <h2>{{$store.state.counter}}</h2>
  </div>
</template>

现在访问首页,计数0已经可以显示出来了。

在组件内,来自store的数据只能读取,不能手动改变,改变store中数据的唯一途径就是显示的提交mutations,用来加1和减1。

const store = new Vuex.Store({
    state: {
        counter: 1000
    },
    mutations: {
        //
        //方法,默认参数为state
        increment(state) {
            state.counter++
        },
        decrement(state) {
            state.counter--
        }
    }
})

在组件内,通过this.$store.commit方法来执行mutations。在App.vue中添加两个按钮用于加和键:

<template>
  <div id="app">
    <h2>App</h2>
    <h2>{{$store.state.counter}}</h2>
    <button @click="handleIncrement">+1</button>
    <button @click="handleDecrease">-1</button>
  </div>
</template>

<script>

  import HelloVuex from './components/HelloVuex'

  export default {
    name: 'App',
    components: {
      
    },
    data() {

    },
    methods: {
      handleIncrement(){
        this.$store.commit('increment')
      },
      handleDecrease(){
        this.$store.commit('decrement')
      }
    }
  }
</script>

<style>

</style>

在这里插入图片描述
在这里插入图片描述

mutations还可以接收第二个参数,可以是数字、字符串或对象等类型。比如每次增加的不是1,而是指定的数量,可以这样改写:

mutations: {
        //方法,默认参数为state
        increment(state, n) {
            state.counter += n
        },
        decrement(state, n) {
            state.counter += n
        }
    }
methods: {
     handleIncrement(){
       this.$store.commit('increment', 10)
     },
     handleDecrease(){
       this.$store.commit('decrement', 10)
     }
   }

提交mutation的另一种方式是直接使用包含type属性的对象,例如:

increment(state, n) {
            state.counter += n.count
        }
handleIncrement(){
        this.$store.commit({
          type: 'increment',
          count: 10
        })
      }

Vuex还有其它三个选项可以使用:getters、actions、modules

getter:(类似组件的计算属性computed)

假如Vuex定义了某个数据List,它是一个数组:

state: {
        counter: 1000,
        list: [1, 5, 8, 10, 30, 50]
        }

如果只想要得到小于10的的数据,可以在getters中定义过滤方法:

getters: {
        //类似组件的计算属性
        filteredList: state => {
            return state.list.filter(item => item < 10)
        }
    }

在App.vue中使用:

<h2>{{$store.getters.filteredList}}</h2>

在这里插入图片描述

getters也可以依赖其它的getter,把getter作为第二个参数,例如再写一个getter,计算出list过滤后的结果的数量:

filteredList: state => {
            return state.list.filter(item => item < 10)
        },
        listCount: (state, getters) => {
            return getters.filteredList.length;
        }
<h2>{{$store.getters.listCount}}</h2>
<h2>{{$store.getters.filteredList}}</h2>

在这里插入图片描述

actions:
mutation中不应该异步操作数据,所以有了actions选项。
action在组件内通过$store.dispatch触发,例如使用action来减1,使用Promise在1秒后提交mutation:

mutations: {
        //
        //方法,默认参数为state
        increment(state, n) {
            state.counter += n.count
        },
        decrement(state, n) {
            state.counter -= n
        }
    },
    actions: {
        //在这里定义异步操作
        asyncDecrement(context){
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    context.commit('decrement', 10)
                    resolve()
                }, 1000)
            })
        }
    }

App.vue:

<template>
  <div id="app">
    <h2>App</h2>
    <h2>{{$store.state.counter}}</h2>
    <button @click="handleIncrement">+1</button>
    <button @click="handleActionDecrease">-1</button>

    <h2>{{$store.getters.listCount}}</h2>
    <h2>{{$store.getters.filteredList}}</h2>

  </div>
</template>

<script>

  export default {
    name: 'App',
    components: {
    
    },
    methods: {
      handleIncrement(){
        this.$store.commit({
          type: 'increment',
          count: 10
        })
      },
      handleActionDecrease(){
        this.$store.dispatch('asyncDecrement').then(() => {
          console.log(this.$store.state.counter);//990
          
        })
      }
    }
  }
</script>

<style>

</style>

在这里插入图片描述

modules:

它用来将store分割到不同模块。当项目足够大时,store里的state、getters、mutations、actions会非常多,都放在一个index.js中就不是很友好,使用modules可以把他们写到不同的文件中。

每个module拥有自己的state、getters、mutations、actions,而且可以多层嵌套。

例如:

const moduleA = {
	state: {...},
	mutations: {...},
	actions: {...},
	getters: {...}
}

const moduleB = {
	state: {...},
	mutations: {...},
	actions: {...},
	getters: {...}
}


const store = new Vuex.Store({
	modules: {
		a: moduleA,
		b: moduleB
	}
})


store.state.a//moduleA的状态
store.state.b//moduleB的状态

另外,module的mutation和getter接受的第一个参数state是当前模块的状态。在actions和getters中,还可以接收一个参数rootState,来访问根节点的状态。比如getters中rootState将作为第三个参数:

const moduleA = {
	state: {
		count: 0
	},
	getters: {
		sumCount (state, getters, rootState) {
			return state.count + rootState.count;
		}
	}
}
发布了716 篇原创文章 · 获赞 2079 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/cold___play/article/details/104148070