vuex初探

WW(是什么、为什么) 

 什么是vuex? 如果你学过react,那么你就更容易理解vuex,因为vuex相当于react中的redux,它是用于管理数据的工具。我们看一看官网的介绍:

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

  为什么要使用vuex? 因为如果不用vuex,我们也可以控制组件之间的通信,但是会非常的难以管理,而通过vuex我们可以更为方便的控制数据在组件之间的通信。 尤其是对于父组件向子组件传递数据,我们可以通过props,而子组件向父组件传递数据,我们可以使用events up。 但是如果希望组件之间的通信(这往往也是最为需求的), 我们就很难处理,这是vuex就派上用场了。

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

   

VUEX核心

  vuex的核心就是一个store(仓库),这个仓库中包含了所有的状态。 关键词: 状态 ---  vue中使用了状态这个词,实际上就是数据,只是这个数据是响应式的, 当store中的状态发生变化时,依赖这个store的组件也会得到高效的更新,值得注意的是: 我们不能随意的改变这个状态,而必须通过特有的方式 --- 显式地提交(commit) mutations。这种方式的好处在于我们可以方便的管理状态的改变。  

VUEX简单实例

在使用下面的实例过程中我们需要先安装vuex,通过npm的方式或者通过使用cdn的方式都是可以的。下面是一个最简单的的例子:

// 如果在模块化构建系统中,请确保在开头调用了 Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

可以看到,我们再使用vue时,无论是vue,还是vue-router,或者是vuex,都需要创建一个实例来使用。 

现在我们可以使用store.state.count的方式来访问状态对象、通过store.commit('increment')的方式触发状态变更 --- 这也是修改store中的状态的唯一方式,所以我们不能通过给store.state.count赋值的方式来修改仓库中的state,这样限制的好处在于我们可以更清晰、容易地来控制数据。

vuex计数应用 

vuex核心概念之一 state

 首先要理解的是vuex使用的是单一状态树,即vuex的状态管理处于一棵树,也许你的应用非常复杂,分为了很多不同的模块,但是每个应用也仅仅包含一个store实例, 我们可以将store分散到各个子模块中去。

 那么我们如果读取到state呢? vuex的方式是将store注册到vue实例中(前提是使用vue.use(vuex)),然后才能获取到状态,

const app = new Vue({
  el: '#app',
  // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})

 即创建了一个实例之后,我们将store注册进来,然后该 store 实例会注入到根组件下的所有子组件中,且子组件可以通过 this.$store访问到状态对象

 访问一个状态我们需要使用计算属性,但是如果我们需要访问到很多状态,那么每一个状态都通过计算属性得到就会非常麻烦,于是vuex提供了mapState。 

vuex核心概念之二Getters

 有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:

computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

  如果有多个组件需要用到此属性,我们要么复制这个函数,或者抽取到一个共享函数然后在多处导入它 —— 无论哪种方式都不是很理想。

 Vuex 允许我们在 store 中定义『getters』(可以认为是 store 的计算属性)。Getters 接受 state 作为其第一个参数。

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

 

vuex核心概念之三mutations

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

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})

 然后通过store.commit('increment')就可以来更改state了。

 提交载荷

 我们使用mutations改变状态,同时在commit时我们可以传递参数,如:

mutations: {
  increment (state, n) {
    state.count += n
  }
}
store.commit('increment', 10)

 但是这里只传入了一个参数,但是对于复杂的页面,我们往往需要传入多个参数,那么传入一个对象是一个不错的选择,这就是payload。如下:

// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit('increment', {
  amount: 10
})

 其中传入的这个对象就是payload。

 当然,在使用提交时,我们还可以换一种风格,即只传一个对象作为参数,把mutations中的方法作为对象的type的值,如下所示:

store.commit({
  type: 'increment',
  amount: 10
})

  并且handler是不变的。 

 值得注意的是: mutation必须是同步函数。

vuex核心概念之四actions

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

下面就是一个简单的actions:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

可以看到action的提交时mutation而不是直接变更状态, 所以mutation是唯一可以变更状态的方法就是成立的了。

vuex核心概念之五modules

  最开始我们说到了state是单一状态树,即整个应用使用一个状态树。 但是又提到了如果应用比较大时,我们的代码一般都是分模块的,那么这个状态树应当是分散的。

  Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割:

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

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

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

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

项目结构

 vuex并不会限制你的代码结构,但是它要求你必须遵守一定的规则:

  1. 应用层级的状态应该集中到单个 store 对象中。

  2. 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。

  3. 异步逻辑都应该封装到 action 里面。

 只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation、和 getters 分割到单独的文件。

  即因为应用比较复杂,所以store的创建导出、action、mutation等代码都比较复杂时,为了使逻辑更为清晰,我们不是将vuex写在一个js文件中,而是分开写,并且放在store文件夹下。

结束

原文地址:https://www.cnblogs.com/zhuzhenwei918/p/6833078.html