VueSupercharge 精通指南:构建超级状态管理 Vue.js 应用

这篇具有很好参考价值的文章主要介绍了VueSupercharge 精通指南:构建超级状态管理 Vue.js 应用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、介绍

1.1 Vuex 是什么 ?

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

1.2 什么是“状态管理模式”?

这个状态自管理应用包含以下几个部分:

状态,驱动应用的数据源;
视图,以声明方式将状态映射到视图;
操作,响应在视图上的用户输入导致的状态变化。

以下是一个表示“单向数据流”理念的简单示意:

VueSupercharge 精通指南:构建超级状态管理 Vue.js 应用,vue.js,前端,javascript

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

  • 多个视图依赖于同一状态。

  • 来自不同视图的行为需要变更同一状态。

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

Vuex就是把组件的共享状态抽取出来,以一个全局单例模式管理 。
通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。

1.3 安装

npm install vuex@next --save

1.4 简单的Vuex使用

1.4.1 store.js

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {},
  actions: {},
})

1.4.2 main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import store from "./store";

Vue.config.productionTip = false

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

1.4.3 App.vue

<template>
  <div>
    <my-addition></my-addition>
    <p>----------------------------------</p>
    <my-subtraction></my-subtraction>
  </div>
</template>

<script>
import Addition from "./components/Addition";
import Subtraction from "./components/Subtraction";

export default {
  data() {
    return {};
  },
  components: {
    'my-addition': Addition,
    'my-subtraction': Subtraction
  }
}
</script>

<style>

</style>

1.4.4 Addition.vue

<template>
  <div>
    <!-- 组件访问State中数据的第一种方式   -->
    <h3>当前最新的count值为:{{$store.state.count}}</h3>
    <button>+1</button>
  </div>
</template>

<script>
export default {
  name: "Addition",
  data() {
    return {};
  }
}
</script>

<style scoped>

</style>

1.4.5 Subtraction.vue

<template>
  <div>
    <h3>当前最新的count值为:{{$store.state.count}}</h3>
    <button>-1</button>
  </div>
</template>

<script>
export default {
  name: "Subtraction",
  data() {
    return {};
  }
}
</script>

<style scoped>

</style>

二、State

2.1 单一状态树

  • Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。

  • 它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。

2.2 方式一:通过$store获取State中数据

$store.state.count

2.3 方式二:通过mapState获取State中数据(推荐)

// 组件访问State中数据的第二种方式--引入
import {mapState} from 'vuex'

// 将全局数据,映射为当前组件的计算属性
...mapState(['count'])

// 模版中使用
<template>
  <div>
    <h3>当前最新的count值为:{{count}}</h3>
    <button>-1</button>
  </div>
</template>

三、Mutation

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

3.1 方式一:使用commit触发mutation

使用commit触发mutation

// store.js
export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    add(state) {
      state.count++;
    }
  },
  actions: {},
})

// Adition.vue
<template>
  <div>
    <!-- 组件访问State中数据的第一种方式   -->
    <h3>当前最新的count值为:{{$store.state.count}}</h3>
    <button @click="addHandler">+1</button>
  </div>
</template>

<script>
export default {
  name: "Addition",
  data() {
    return {};
  },
  methods: {
    addHandler() {
      // 这种方式是不合法的!!!
      // this.$store.state.count++;

      // 触发mutation的第一种方式
      this.$store.commit('add')
    }
  }
}
</script>

<style scoped>

</style>

带参数的mutation

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    add(state) {
      state.count++;
    },
    // 第二位就是,传入的参数。如果是多个参数可以传入对象
    addN(state, step) {
      state.count += step;
    },
    sub(state) {
      state.count--;
    },
  },
  actions: {},
})
// Addition.vue
<template>
  <div>
    <!-- 组件访问State中数据的第一种方式   -->
    <h3>当前最新的count值为:{{$store.state.count}}</h3>
    <button @click="addHandler">+1</button>
    <button @click="addNHandler">+N</button>
  </div>
</template>

<script>
export default {
  name: "Addition",
  data() {
    return {};
  },
  methods: {
    addHandler() {
      // 这种方式是不合法的!!!
      // this.$store.state.count++;

      // 触发mutation的第一种方式
      this.$store.commit('add')
    },
    addNHandler() {
      this.$store.commit('addN', 3)
    }
  }
}
</script>

<style scoped>

</style>

3.2 方式二:使用mapMutation触发mutation(推荐)

store.js

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    add(state) {
      state.count++;
    },
    addN(state, step) {
      state.count += step;
    },
    sub(state) {
      state.count--;
    },
    subN(state, step) {
      state.count -= step;
    },
  },
  actions: {},
})

Subtraction.vue

<template>
  <div>
    <h3>当前最新的count值为:{{count}}</h3>
    <button @click="subHandler">-1</button>
    <button @click="subNHandler">-N</button>
  </div>
</template>

<script>
// 组件访问State中数据的第二种方式--引入
import {mapState, mapMutations} from 'vuex'

export default {
  name: "Subtraction",
  data() {
    return {};
  },
  computed: {
    // 将全局数据,映射为当前组件的计算属性
    ...mapState(['count'])
  },
  methods: {
    ...mapMutations(['sub', 'subN']),
    // 将全局mutations函数映射为组件中的函数
    subHandler() {
      this.sub();
    },
    subNHandler() {
      this.subN(3)
    }
  }
}
</script>

<style scoped>

</style>


四、Action

Action的作用是执行异步函数,因为mutation中无法执行异步函数。在mutation中使用异步函数会导致state的状态无法被及时追踪导致代码异常!!!

4.1 方式一:使用dispatch调用Action中的异步函数

4.1.1 store.js

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    add(state) {
      // setTimeout(() => {
      //   // 不要在mutations中执行异步操作,会造成vuex存储状态不可追踪
      //   state.count++;
      // }, 1000)
      state.count++;
    },
    addN(state, step) {
      state.count += step;
    },
    sub(state) {
      state.count--;
    },
    subN(state, step) {
      state.count -= step;
    },
  },
  actions: {
    // context: 可以理解为当前的Vuex.Store实例对象
    addAsync(context) {
      setTimeout(() => {
        // 在 actions 中,不能直接修改 state 中的数据
        // 必须通过 context.commit() 触发某个 mutations 才行
        context.commit('add')
      }, 1000)
    },
    addNAsync(context, step) {
      setTimeout(() => {
        // 在 actions 中,不能直接修改 state 中的数据
        // 必须通过 context.commit() 触发某个 mutations 才行
        context.commit('addN', step)
      }, 1000)
    }
  },
})

4.1.2 Addition.vue

<template>
  <div>
    <!-- 组件访问State中数据的第一种方式   -->
    <h3>当前最新的count值为:{{$store.state.count}}</h3>
    <button @click="addHandler">+1</button>
    <button @click="addNHandler">+N</button>
    <button @click="addHandlerAsync">+1 Async</button>
    <button @click="addNHandlerAsync">+N Async</button>
  </div>
</template>

<script>
export default {
  name: "Addition",
  data() {
    return {};
  },
  methods: {
    addHandler() {
      // 这种方式是不合法的!!!
      // this.$store.state.count++;

      // 触发mutation的第一种方式
      this.$store.commit('add')
    },
    addNHandler() {
      this.$store.commit('addN', 3)
    },
    addHandlerAsync() {
      // 这里的 dispatch 专门用来触发action函数
      this.$store.dispatch('addAsync')
    },
    addNHandlerAsync() {
      // 这里的 dispatch 专门用来触发action函数
      this.$store.dispatch('addNAsync', 3)
    }
  }
}
</script>

<style scoped>

</style>

4.2 方式二:使用mapAction调用Action中的异步函数

4.2.1 store.js

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    add(state) {
      // setTimeout(() => {
      //   // 不要在mutations中执行异步操作,会造成vuex存储状态不可追踪
      //   state.count++;
      // }, 1000)
      state.count++;
    },
    addN(state, step) {
      state.count += step;
    },
    sub(state) {
      state.count--;
    },
    subN(state, step) {
      state.count -= step;
    },
  },
  actions: {
    // context: 可以理解为当前的Vuex.Store实例对象
    addAsync(context) {
      setTimeout(() => {
        // 在 actions 中,不能直接修改 state 中的数据
        // 必须通过 context.commit() 触发某个 mutations 才行
        context.commit('add')
      }, 1000)
    },
    addNAsync(context, step) {
      setTimeout(() => {
        // 在 actions 中,不能直接修改 state 中的数据
        // 必须通过 context.commit() 触发某个 mutations 才行
        context.commit('addN', step)
      }, 1000)
    },
    subAsync(context) {
      setTimeout(() => {
        context.commit('sub')
      }, 1000)
    },
    subNAsync(context, step) {
      setTimeout(() => {
        context.commit('subN', step)
      }, 1000)
    }
  },
})

4.2.2  Subtraction.vue

<template>
  <div>
    <h3>当前最新的count值为:{{count}}</h3>
    <button @click="subHandler">-1</button>
    <button @click="subNHandler">-N</button>
    <button @click="subHandlerAsync">-1 Async</button>
    <button @click="subNHandlerAsync">-N Async</button>
  </div>
</template>

<script>
// 组件访问State中数据的第二种方式--引入
import {mapState, mapMutations, mapActions} from 'vuex'

export default {
  name: "Subtraction",
  data() {
    return {};
  },
  computed: {
    // 将全局数据,映射为当前组件的计算属性
    ...mapState(['count'])
  },
  methods: {
    ...mapMutations(['sub', 'subN']),
    ...mapActions(['subAsync', 'subNAsync']),
    // 将全局mutations函数映射为组件中的函数
    subHandler() {
      this.sub();
    },
    subNHandler() {
      this.subN(3)
    },
    subHandlerAsync() {
      this.subAsync();
    },
    subNHandlerAsync() {
      this.subNAsync(3)
    }
  }
}
</script>

<style scoped>

</style>

五、Getters

Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

5.1 创建Getter方法

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    add(state) {
      // setTimeout(() => {
      //   // 不要在mutations中执行异步操作,会造成vuex存储状态不可追踪
      //   state.count++;
      // }, 1000)
      state.count++;
    },
    addN(state, step) {
      state.count += step;
    },
    sub(state) {
      state.count--;
    },
    subN(state, step) {
      state.count -= step;
    },
  },
  actions: {
    // context: 可以理解为当前的Vuex.Store实例对象
    addAsync(context) {
      setTimeout(() => {
        // 在 actions 中,不能直接修改 state 中的数据
        // 必须通过 context.commit() 触发某个 mutations 才行
        context.commit('add')
      }, 1000)
    },
    addNAsync(context, step) {
      setTimeout(() => {
        // 在 actions 中,不能直接修改 state 中的数据
        // 必须通过 context.commit() 触发某个 mutations 才行
        context.commit('addN', step)
      }, 1000)
    },
    subAsync(context) {
      setTimeout(() => {
        context.commit('sub')
      }, 1000)
    },
    subNAsync(context, step) {
      setTimeout(() => {
        context.commit('subN', step)
      }, 1000)
    }
  },
  getters: {
    showNum(state) {
      return '当前最新的数量是【' + state.count + '】';
    }
  }
})

5.2 方法一:$store.getter调用

<template>
  <div>
    <!-- 组件访问State中数据的第一种方式   -->
    <h3>{{$store.getters.showNum}}</h3>
    <button @click="addHandler">+1</button>
    <button @click="addNHandler">+N</button>
    <button @click="addHandlerAsync">+1 Async</button>
    <button @click="addNHandlerAsync">+N Async</button>
  </div>
</template>

<script>
export default {
  name: "Addition",
  data() {
    return {};
  },
  methods: {
    addHandler() {
      // 这种方式是不合法的!!!
      // this.$store.state.count++;

      // 触发mutation的第一种方式
      this.$store.commit('add')
    },
    addNHandler() {
      this.$store.commit('addN', 3)
    },
    addHandlerAsync() {
      // 这里的 dispatch 专门用来触发action函数
      this.$store.dispatch('addAsync')
    },
    addNHandlerAsync() {
      // 这里的 dispatch 专门用来触发action函数
      this.$store.dispatch('addNAsync', 3)
    }
  }
}
</script>

<style scoped>

</style>

5.3 方法二:mapGetters方式调用

<template>
  <div>
    <h3>{{showNum}}</h3>
    <button @click="subHandler">-1</button>
    <button @click="subNHandler">-N</button>
    <button @click="subHandlerAsync">-1 Async</button>
    <button @click="subNHandlerAsync">-N Async</button>
  </div>
</template>

<script>
// 组件访问State中数据的第二种方式--引入
import {mapState, mapMutations, mapActions, mapGetters} from 'vuex'

export default {
  name: "Subtraction",
  data() {
    return {};
  },
  computed: {
    // 将全局数据,映射为当前组件的计算属性
    ...mapState(['count']),
    // 将全局的getters,映射为当前组件的计算属性
    ...mapGetters(['showNum'])
  },
  methods: {
    ...mapMutations(['sub', 'subN']),
    ...mapActions(['subAsync', 'subNAsync']),
    // 将全局mutations函数映射为组件中的函数
    subHandler() {
      this.sub();
    },
    subNHandler() {
      this.subN(3)
    },
    subHandlerAsync() {
      this.subAsync();
    },
    subNHandlerAsync() {
      this.subNAsync(3)
    }
  }
}
</script>

<style scoped>

</style>

六、其他

6.1 modules

Module | Vuex

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:文章来源地址https://www.toymoban.com/news/detail-806866.html

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 的状态

到了这里,关于VueSupercharge 精通指南:构建超级状态管理 Vue.js 应用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue状态管理库-Pinia

    Pinia 是 Vue 的专属状态管理库,它允许支持跨组件或页面共享状态,即共享数据,他的初始设计目的是设计一个支持组合式API的 Vue 状态管理库(因为vue3一个很大的改变就是组合式API),当然这并不是说Pinia只支持vue3,他是同时支持vue2和vue3的, 本文倾向于拥抱Vue3,所以代码语

    2024年02月22日
    浏览(42)
  • Vue--》探索Pinia:Vue状态管理的未来

    目录 Pinia的讲解与使用 Pinia的安装与使用 store数据操作 解构store数据

    2024年02月05日
    浏览(32)
  • Vue使用 Pinia 进行状态管理

    Pinia 是一个适用于 Vue.js 的状态管理库,它采用了组合式 API 的理念,使得状态管理变得更加简单、直观和灵活。与传统的 Vuex 相比,Pinia 提供了更好的 TypeScript 支持,同时也更加适合大型应用程序和复杂状态逻辑的管理。 首先,我们需要在 Vue 项目中安装 Pinia。你可以通过

    2024年02月13日
    浏览(48)
  • 【Vue全家桶】Pinia状态管理

    🤗这里是前端程序员小张! 🌻人海茫茫,感谢这一秒你看到这里。希望我的文章对你的有所帮助! 🌟愿你在未来的日子,保持热爱,奔赴山海! Pinia开始于大概2019年,其目的是设计一个拥有 组合式 API 的 Vue 状态管理库 目前同时兼容Vue2、Vue3,也并不要求你使用Compositio

    2023年04月09日
    浏览(42)
  • 【Vue】使用 Vuex 作为状态管理

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式和库。它使用单一状态树,这意味着这个对象包含了全部的应用层级状态,并且以一种相对集中的方式存在。这也意味着,通常单个项目中只有一个 Vuex store。Vuex 的核心概念和功能包括: 状态(State) :Vuex 使用单一状态树

    2024年01月23日
    浏览(45)
  • Vue | Vue.js 全家桶 Pinia状态管理

    🖥️ Vue .js专栏:Node.js Vue.js 全家桶 Pinia状态管理 🧑‍💼 个人简介:一个不甘平庸的平凡人🍬 ✨ 个人主页:CoderHing的个人主页 🍀 格言: ☀️ 路漫漫其修远兮,吾将上下而求索☀️ 👉 你的一键三连是我更新的最大动力❤️ 目录 一、Pinia和Vuex的对比 什么是Pinia呢? Pina和

    2024年01月16日
    浏览(37)
  • Vue.js与后端交互:构建动态数据应用的完美指南

    「作者主页」 :雪碧有白泡泡 「个人网站」 :雪碧的个人网站 「推荐专栏」 : ★ java一站式服务 ★ ★ 前端炫酷代码分享 ★ ★ uniapp-从构建到提升 ★ ★ 从0到英雄,vue成神之路 ★ ★ 解决算法,一个专栏就够了 ★ ★ 架构咱们从0说 ★ ★ 数据流通的精妙之道★ Vue.js是一

    2024年02月17日
    浏览(31)
  • vue3学习-Pinia状态管理

    定义一个Store 这个 name ,也称为 id ,是必要的,Pinia 使用它来将 store 连接到 devtools。 将返回的函数命名为 use… 是跨可组合项的约定,以使其符合你的使用习惯。 使用 store 一旦 store 被实例化,你就可以直接在 store 上访问 state 、 getters 和 actions 中定义的任何属性 store 是一

    2024年02月14日
    浏览(31)
  • vue­-router路由和前端状态 管理

    vue­-router路由基本加载 可以分为四步 :具体流程如下 : 安装 在命令行中 进入到自己的项目目录输入一下命令 安装依赖: npm install --save vue-router 在需要用到路由跳转的模块中引用(本文是在在入口文件 main.js 进行设置) import router from ‘vue-router’ Vue.use(router) 配置路由文件,

    2024年02月02日
    浏览(35)
  • vue全家桶进阶之路39:Vue3 状态管理

    Vue3 的状态管理主要是通过 Vuex 4 来实现。Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。 在Vue3的状态管理中,以下是各个属性的作用: state :存储应用程序中的状

    2023年04月18日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包