Vuex的基本原理和简单使用

什么是Vuex,有什么用?

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

普通的Vue状态自管理在遇到多个视图共同依赖同一状态,或者会改变同一状态时,会遇到难以管理,难以维护的麻烦。为了解决这个麻烦,Vue官方基于全局单例模式提供了Vuex状态管理框架。

在Vuex框架中,Vue视图,状态,数据之间的关系如下图所示:

image

什么时候应该使用Vuex,什么时候不要使用?

如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。

如何使用Vuex

创建一个Vuex的状态管理仓库

  1. 安装Vuex框架:
    我们通过如下命令为Vue项目中添加Vuex框架
npm i Vuex

如下图所示:
image
2. 在main.js中引入Vuex框架,并通过use命令加载到Vue中

import Vuex from 'vuex'
Vue.use(Vuex)
  1. 创建一个store仓库,并把store仓库注册到Vue全局中;store仓库包含state(单一状态树,提供响应式数据),getters(store的计算属性),mutations(改变store状态的方法),actions(处理异步操作,触发mutation)
    image
const store = new Vuex.Store({
  state:{
  },
  mutations:{
  },
  actions:{
  },
  getters:{
  }
})

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

mutations

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数.

你不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法

actions

Action 类似于 mutation,不同在于:

  1. Action 提交的是 mutation,而不是直接变更状态。
  2. Action 可以包含任意异步操作。
  3. Action的分发使用关键字
  1. 为store仓库创建单一状态树State,并创建mutations方法修改state
const store = new Vuex.Store({
  state:{
    count:0
  },
  mutations:{
    increment(state,n){
      state.count+=n
      console.log(state.count)
    }
  },
  actions:{
  },
  getters:{
      
  }
})
  1. 到此为止,Vue中的组件就可以使用store状态仓库了。因为在main.js中,我们通过new Vue将store仓库注册到Vue全局中,所以我们在模板中可以通过this.$store的方式获取到我们store仓库。下面的示例展示了通过组件的计算属性computed定义count变量并通过模板语法展现store状态仓库中的count值。
<template>
  <div id="app">
    {{count}}
  </div>
</template>

<script>

export default {
  name: 'App',
  components: {
    
  },
  computed:{
    count(){
      return this.$store.state.count
    }
  },
  methods:{
  }
}

效果如下:
image
6. 我们当然可以修改store的count值。我们先采用以前的模板事件来修改。

<template>
  <div id="app">
    {{count}}
    <input type="button" @click="handleClick" value="Count++" />
  </div>
</template>

<script>

export default {
  name: 'App',
  components: {
    
  },
  computed:{
    count(){
      return this.$store.state.count
    }
  },
  methods:{
    handleClick(){
      return this.$store.state.count++;
    }
  }
}
</script>

效果如下:
image
7. 但是Vue并不鼓励我们采用这样的方式来修改store的count值。这样管理依然不方便,很有可能造成混乱。按照上面对mutations的介绍,我们可以猜到Vuex鼓励我们通过mutations对store的state进行修改,这样我们对state的修改过程才会被Vuex记录下来。我们先前在初始化state时,同步初始化了mutations:我们创建了一个叫increment的方法,现在我们只需要调用这个方法即可。每一个mutations中的方法本质都是一个回调函数,处理sate状态的逻辑都包含在里面,接收state参数。mutations方法可以多接收一个额外参数(提交荷载),如果希望传入多个数据,则应该组织成对象再传入(示例中仅仅是一个简单的number)

mutations:{
    increment(state,n){
      state.count+=n
      console.log(state.count)
    }
  },
  1. Vuex中的mutations方法不能被直接调用,必须被actions或模板以commit的形式调用。我们先尝试使用模板直接commit的形式调用(假设我们没有异步操作需要处理,完全可以绕过actions)
<template>
  <div id="app">
    {{count}}
    <input type="button" name="count2" @click="$store.commit('increment',2)" value="Count+2" /> 
  </div>
</template>

<script>

export default {
  name: 'App',
  components: {
    
  },
  computed:{
    count(){
      return this.$store.state.count
    }
  },
  methods:{
  }
}
</script>

<style>
</style>

  1. 我们通过click事件直接对store进行了commit操作,commit调用时传入了两个参数,第一个是回调函数名:increment,另一个是提交荷载:一个整数;效果如下:
    image
  2. 到此为止,我们一直是使用的Vue组件的compute属性展示的sotre。如果有多个组件需要用到此属性,我们要么复制这个函数,或者抽取到一个共享函数然后在多处导入它——无论哪种方式都不是很理想。先前介绍过:getters是sotre的computer,那么我们完全可以在sotre的getters中处理展示逻辑。
const store = new Vuex.Store({
  state:{
    count:0
  },
  mutations:{
    increment(state,n){
      state.count+=n
      console.log(state.count)
    }
  },
  actions:{
  },
  getters:{
    doubleCount(state){
      return state.count * 2
    }
  }
})
<template>
  <div id="app">
    {{$store.getters.doubleCount}}
    <input type="button" name="count2" @click="$store.commit('increment',2)" value="Count+2" /> 
  </div>
</template>

<script>

export default {
  name: 'App',
  components: {
  },
  computed:{
  },
  methods:{
  }
}
</script>

<style>
</style>

效果如下:
image
11. 我们一直还没有使用到store的actions。根据官网描述,actions与mutation很像,不同的是用来触发(commit)mutation而不是直接修改状态,最重要的是我们可以在actions中处理异步逻辑,调用远程API等等(如下示例中,利用模拟异步等待);前台调用是使用dispatch关键字调用。

const store = new Vuex.Store({
  state:{
    count:0
  },
  mutations:{
    increment(state,n){
      state.count+=n
      console.log(state.count)
    }
  },
  actions:{
    increment(state,n){
      setTimeout(() => {
        state.commit('increment',n)
      },1000);
    }
  },
  getters:{
    doubleCount(state){
      return state.count * 2
    }
  }
})
<template>
  <div id="app">
    {{$store.getters.doubleCount}}
    <input type="button" name="count1" @click="$store.dispatch('increment',3)" value="Count+3" /> 
  </div>
</template>

<script>

export default {
  name: 'App',
  components: {
    
  },
  computed:{
  },
  methods:{
  }
}
</script>

<style>
</style>

效果如下:
image

组件调用Vuex关键字的方法总结

image

posted @ 2020-02-16 19:03  文鹏  阅读(1588)  评论(0编辑  收藏  举报