欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Vuex入门(1)—— Vuex的设计初衷和简单使用

程序员文章站 2024-03-01 19:20:46
...

  开一个Vuex的坑.

  先来谈谈个人看法,之前很早的时候就用过Vuex做组件间通信,对于单页面应用来说,也就是不同的router子组件的一些数据通信,当然我也尝试过event bus的解决方案,这里不进行横向对比了,如果想做组件间的复杂通信,直接选择Vuex即可(个人建议).如果有人想学习Vuex,个人推荐是直接去官网的API,当然官网的API会让你先了解一下ES6的语法,当时也是看到那句话就比较反感那个文档,不过还是屁颠屁颠的把ES6的语法过了一遍,有兴趣的可以去我的分类里简单学习一下.关于这个系列肯定会有后续的展开,主要包括一些Vuex的核心概念(State,Getter,Mutation,Action,Module),但个人推荐不用深入了解Vuex,如果需求不是那么复杂的话,基本上你稍微了解一下今天的例子,知道如何用state存储状态,如何用mutation触发状态变更就可以完成大部分项目需求.

  Vuex的设计初衷就是为了解决Vue中单项数据流的问题,什么是单项数据流,简单来说就是

  父组件可以传值给子组件,你可以用props,还相对简单.

  子组件可以传值给父组件,你可以用$emit,这个算相对难一丢丢.

  这并不是单项数据流的官方解释,是我自己随便总结的,来看这种数据交互方式会产生什么问题

 1.祖祖祖父组件要传值给曾曾曾孙,这就有点尴尬了,一个简单的数据要从祖宗十八代传到你这一代,得经历子组件的一个个祖辈,而且中间还不能断,这又不是传家宝,传那么多次又不会升值,所以这个问题是Vue的设计中未考虑完善的.

 2.兄弟节点间的通信问题,可能需要父组件的支持,然而凭什么你和你兄弟的事情非得让你爸知道呢?这个问题在Vue的设计中也不好解决.

  为了解决上述问题,Vuex提出了一个'公共仓库'(store)的概念,“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state).你的所有组件都可以访问这个容器中的公共状态,这有点像你定义了一个全局变量,因此你可以在当前代码块的所有位置访问到这个变量.当然store容器和全局变量还是有很大的区别的.

  1.Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

  2.你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

  前面两点是官网的说明,谈谈个人理解,首先第一点,由于使用Vuex需要将store实例挂载到Vue实例中,因此Vue实例可以对Vuex的state数据加监听,这跟Vue实例data的数据双向绑定是类似的.而全局变量由于没有被"数据劫持",因此即使全局变量的值发生改变,也无法在Vue实例中监听到他的变化.第二点更好理解一些,就是Vuex中的状态值,不能通过赋值的方式(state.xxx = yyy)改变,需要通过mutation触发变更,这样做方便状态管理,而一般的全局变量是支持直接赋值的.

 下面来实现一个简单的例子,用vuex做一些事情

 首先,项目是基于vue-cli脚手架搭的,你可以用npm的方式导入vuex,并通过Vue.use(Vuex)的显示声明方式来使用Vuex

   Vuex入门(1)—— Vuex的设计初衷和简单使用

  在项目中,我通过store文件夹来管理vuex的一些模块,今天要用到的模块只有state模块和mutation模块,这也是Vuex状态管理的最基本的两个模块.

  要使用Vuex,你还需要在main.js的Vue根实例中挂载一下store实例,如下所示

//main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/index'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store, // 挂在store到所有子组件中
  components: { App },
  template: '<App/>'
})

 准备工作都完成了.我们在store里面存一个count用于后续操作.

//state.js
let state = {
  count: 1
}
export default state

 存入后,我们就可以在任意子组件中访问这个值了,在vue的子组件中我们可以通过this.$store访问store对象,注意这里我用了computed接收了store的值,这有利于在值发生改变的时候及时的响应到当前子组件.

<template>
  <div id="example">
    {{count}}
  </div>
</template>
<script>
export default {
  computed: {
    count () {
      return this.$store.state.count
    }
  },
  methods: {
  }
}
</script>
<style lang="less" scoped>
</style>

  完成了值的接收,下面来对这个值进行一些操作,注意,如果要操作state中的值,不能直接通过this.$store.state.xxx = yyy的方式进行暴力修改,必须要提交给mutation处理,这在之前也有提过,所以我们要在mutation.js里写入对state的操作

//mutation.js
// 第一个参数默认接收state对象
let increment = (state) => {
  state.count++
}
let decrement = (state) => {
  state.count--
}
export {increment, decrement}

  然后我们就可以通过this.$store.commit('function')修改这个值了.

<template>
  <div id="example">
    <button @click="decrement">-</button>
    {{count}}
    <button @click="increment">+</button>
  </div>
</template>
<script>
export default {
  computed: {
    count () {
      return this.$store.state.count
    }
  },
  methods: {
    increment () {
      this.$store.commit('increment')
    },
    decrement () {
      this.$store.commit('decrement')
    }
  }
}
</script>
<style lang="less" scoped>
</style>

 这里没有涉及到通信的问题,但事实上Vuex已经帮你做了状态管理了,如果别的子组件用到了上述的count,在count改变的时候,其他的子组件也会相应到count的改变,有兴趣的自己动手试一试,这里不婆婆妈妈啰啰嗦嗦了.

 后续文章会深入探究Vuex的API和坑,欢迎关注~