Vuex使用

  1. 1. 什么是vuex
  2. 2. 什么情况下我应该使用 Vuex?
  • 开始
    1. 1. 最简单的 Store
  • State
    1. 1. 在 Vue 组件中获得 Vuex 状态
  • 1.在Vue-cli中的Vuex
  • 2.Vuex的使用
  • 3.在Composition API中使用Vuex。

  • 什么是vuex

    官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

    当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:

    • 多个视图依赖于同一状态。
    • 来自不同视图的行为需要变更同一状态。

    对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。

    以上的这些模式非常脆弱,通常会导致无法维护的代码。

    因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!

    通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。

    什么情况下我应该使用 Vuex?

    Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。

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

    Flux 架构就像眼镜:您自会知道什么时候需要它。

    开始

    每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的**状态 (state)**。Vuex 和单纯的全局对象有以下两点不同:

    1. Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
    2. 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

    最简单的 Store

    安装 Vuex 之后,让我们来创建一个 store。创建过程直截了当——仅需要提供一个初始 state 对象和一些 mutation:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import { createApp } from 'vue'
    import { createStore } from 'vuex'

    // 创建一个新的 store 实例
    const store = createStore({
    state () {
    return {
    count: 0
    }
    },
    mutations: {
    increment (state) {
    state.count++
    }
    }
    })

    const app = createApp({ /* 根组件 */ })

    // 将 store 实例作为插件安装
    app.use(store)

    现在,你可以通过 store.state 来获取状态对象,并通过 store.commit 方法触发状态变更:

    1
    2
    3
    store.commit('increment')

    console.log(store.state.count) // -> 1

    在 Vue 组件中, 可以通过 this.$store 访问store实例。现在我们可以从组件的方法提交一个变更:

    1
    2
    3
    4
    5
    6
    methods: {
    increment() {
    this.$store.commit('increment')
    console.log(this.$store.state.count)
    }
    }

    ​ 再次强调,我们通过提交 mutation 的方式,而非直接改变 store.state.count,是因为我们想要更明确地追踪到状态的变化。这个简单的约定能够让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让我们有机会去实现一些能记录每次状态改变,保存状态快照的调试工具。有了它,我们甚至可以实现如时间穿梭般的调试体验。

    由于 store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅需要在计算属性中返回即可。触发变化也仅仅是在组件的 methods 中提交 mutation。

    State

    Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。

    在 Vue 组件中获得 Vuex 状态

    那么我们如何在 Vue 组件中展示状态呢?由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 创建一个 Counter 组件
    const Counter = {
    template: `<div>{{ count }}</div>`,
    computed: {
    count () {
    return store.state.count
    }
    }
    }

    每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。

    然而,这种模式导致组件依赖全局状态单例。

    在模块化的构建系统中,在每个需要使用 state 的组件中需要频繁地导入,并且在测试组件时需要模拟状态。

    Vuex 通过 Vue 的插件系统将 store 实例从根组件中“注入”到所有的子组件里。且子组件能通过 this.$store 访问到。
    让我们更新下 Counter的实现:
    1
    2
    3
    4
    5
    6
    7
    8
    const Counter = {
    template: `<div>{{ count }}</div>`,
    computed: {
    count () {
    return this.$store.state.count
    }
    }
    }

    1.在Vue-cli中的Vuex

    ​ 在src文件夹中会出现一个store文件夹,此文件夹中有一个index.js文件,这就是Vuex模块的js文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import { createStore } from 'vuex'

    // Vuex 数据管理框架
    export default createStore({
    state: {
    },
    getters: {
    },
    mutations: {
    },
    actions: {
    },
    modules: {
    }
    })

    2.Vuex的使用

    Vuex中有五个默认的基本对象:

    • state: state就是Vuex中的公共的状态, 可以将state看作是全局唯一的共享数据仓库。
      类似Vue中的data。(state是所以组件共享的;data是某个组件独有的。)

    • getters: state 的计算属性,类似Vue中的computed 计算属性。

    • mutations:声明方法,用于修改state。类似Vue中的mothods方法。(只能修改同步数据)。

    • actions:声明方法,用于修改state。类似Vue中的mothods方法。(可以修改异步数据)。比如调用api接口都在这里完成。

    • modules:store的子模块,只在开发大型项目的时候会用的上。

    3.在Composition API中使用Vuex。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <template>
    <div>
    <div>这是home {{$store.state.num}}</div>
    </div>
    </template>

    <script>
    import { useRoute } from "vue-router";
    import {useStore} from 'vuex';

    export default {
    name: "AboutView",
    setup(){
    const route = useRoute();
    console.log(route.query.age);

    const store = useStore();
    console.log("store.state.num="+store.state.num)
    console.log("store.getters.newNum="+store.getters.newNum)
    console.log("store.state.num="+store.state.num)
    }
    }
    </script>

    <style scoped>

    </style>
    • 先import导入useStore模块。

    • 通过useStore模块获取store对象。就可以通过store对象获取Vuex中的所有数据了。