【Vuex】Vuex详解,一篇文章搞懂Vuex详细使用过程和代码编写

本篇博客跟学视频链接:Vuex从入门到实战_bilibili

1. 组件之间数据共享

  • 父向子传值:v-bind 属性绑定

  • 子向父传值:v-on 事件绑定

  • 兄弟组件之间共享数据:EventBus

    • $on 接收数据的那个组件

    • $emit 发送数据的那个组件

2. Vuex概述

  • 实现组件全局(数据)管理的一种机制,可以方便的实现组件之间共享数据,不同于上述三种传递值的方式。
  • 可以把vuex当成一个store仓库,可以集中管理共享的数据,并且存储在vuex中的数据都是响应式的,数据与页面同步。
  • 一般情况下,只有组件之间共享的数据,才有必要存储到vuex中;对于组件中的私有数据,依旧存储在组件自身的data中。

3.Vuex基本使用

1)安装vuex依赖

npm install vuex --save

2)导入vuex包

import Vuex from 'vuex'
Vue.use(Vuex)

3)创建store对象

const store = new Vuex.Store({
    // state 中存放全局共享的数据
    state: {count:0}
})

4)store对象挂载到vue实例中

new Vue({
	el: '#app',
	render: h=>h(app),
	router,
	// 创建的共享数据挂载到vue实例
	// 所有组件能够直接从store中获取到全局的数据
	store
})

5)利用vue ui脚手架创建vue项目

复习一下吧:[保姆级教学]使用Vue ui创建一个完整的vue项目_使用vue ui创建vue项目-CSDN博客

  • 详见另一篇文档

3. 项目基础知识

1)格式化

  • 项目下创建文件.prettierrc,应与.gitignore同级,两句代码分别代表:去除分号,用单引号替换双引号。
{
    "semi": false, 
    "singleQuote": true
}

2)git提交

在这里插入图片描述

4. Vuex核心概念

1)State

  • State 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 State 中进行存储。
 // 创建store数据源,提供唯一公共数据
 const store = new Vuex.Store({
 	state: { count: 0 }
 })
1:访问State方法一
  • 注意在唯一根组件template中,可以省略this不写

在这里插入图片描述

2:访问State方法二
  • 导入mapState并把所需要的State域中的属性映射为当前组件的计算属性。

在这里插入图片描述

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

<script>
import { mapState } from 'vuex';
export default {
    data() {
        return {}
    },
    // 把State全局域中的数据映射为我当前组件的计算属性
    computed: {
        ...mapState(['count'])
    }
}
</script>

2)Mutation

store.js

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

Vue.use(Vuex)

export default new Vuex.Store({
  // 定义唯一的state域变量
  state: {
    count: 0
  },
  // 只有 mutations 中定义的函数,才有权利修改 state 中的数据
  // 注意mutations中的方法第一个参数必须是state而且必须带,否则无法调用state中的变量
  mutations: {
    // 不带参mutations
    add(state) {
      state.count++
    },
    // 带参数的mutations
    addN(state, step) {
      state.count += step
    },
    sub(state) {
      state.count--
    },
    subN(state, step) {
      state.count -= step
    }
  }
})
1:触发Mutation方法一
  • 在vuex中不允许组件直接去修改全局域中的数据,必须通过Mutation来变更Store中的数据。 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化(可以监控是谁更改了State)。

addition.vue

<template>
  <div>
    <!-- <h3>当前最新的count值为:{{$store.state.count}}</h3> -->
    <h3>{{$store.getters.showNum}}</h3>
    <!-- 点击该按钮调用Mutation使count值+1 -->
    <button @click="btnHandler1">+1</button>
    <!-- 点击该按钮调用Mutation使count值+N -->
    <button @click="btnHandler2">+N</button>
  </div>
</template>

<script>
export default {
  data() {
    return {}
  },
  // methods方法实际调用的是vuex中的Mutation来改变State域中的值
  methods: {
    btnHandler1() {
      this.$store.commit('add')
      // this.$store.count++; // 不要在本组件中直接修改State域中数据的值
    },
    btnHandler2() {
      // commit 的作用,就是调用 某个 mutation 函数
      this.$store.commit('addN', 3)
    },
  }
}
</script>
2:触发Mutation方法二
  • 同样的,用一个mapMutations将全局的Mutation函数映射到本组件中。

subtraction.vue

<template>
  <div>
    <!-- <h3>当前最新的count值为:{{count}}</h3> -->
    <h3>{{showNum}}</h3>
    <button @click="btnHandler1">-1</button>
    <button @click="subN(3)">-N</button>
  </div>
</template>

<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'

export default {
  data() {
    return {}
  },
  computed: {
    ...mapState(['count']),
    ...mapGetters(['showNum'])
  },
  methods: {
    ...mapMutations(['sub', 'subN']), // 注册sub和subN函数
    btnHandler1() {
      this.sub()
    }
  }
}
</script>

3)Action

  • 如果我们想书写一个异步操作,如单击+1后等待1s后state域中的值才会发生变化,我们可以用js中的定时器来实现,但是vue不能在mutations函数中执行异步操作,此时我们引入Action。
  • Action 用于处理异步任务。如果通过异步操作变更数据,必须通过 Action,而不能使用 Mutation,但是在 Action 中还是要通过触发Mutation 的方式间接变更数据。
1:触发Action方式一

store.js

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

Vue.use(Vuex)

export default new Vuex.Store({
  // 定义唯一的state域变量
  state: {
    count: 0
  },
  mutations: {
    add(state) {
      // 不要在 mutations 函数中,执行异步操作
      // setTimeout(() => {
      //   state.count++
      // }, 1000)
      state.count++
    },
    addN(state, step) {
      state.count += step
    },
    sub(state) {
      state.count--
    },
    subN(state, step) {
      state.count -= step
    }
  },
  actions: {
    addAsync(context) {
      setTimeout(() => {
        // 在 actions 中,不能直接修改 state 中的数据;
        // 必须通过 context.commit() 触发某个 mutation 才行
        context.commit('add')
      }, 1000)
    },
    addNAsync(context, step) {
      setTimeout(() => {
        context.commit('addN', step)
      }, 1000)
    },
})

  • commit函数用于触发Mutations,而dispatch函数用于触发Action,注意Action无法直接修改state域中的值,还是必须通过Mutations来间接的修改state域中的值。

Addition.vue

<template>
  <div>
    <!-- <h3>当前最新的count值为:{{$store.state.count}}</h3> -->
    <h3>{{$store.getters.showNum}}</h3>
    <!-- 点击该按钮调用Mutation使count值+1 -->
    <button @click="btnHandler1">+1</button>
    <!-- 点击该按钮调用Mutation使count值+N -->
    <button @click="btnHandler2">+N</button>
    <button @click="btnHandler3">+1 Async</button>
    <button @click="btnHandler4">+N Async</button>
  </div>
</template>

<script>
export default {
  data() {
    return {}
  },
  // methods方法实际调用的是vuex中的Mutation来改变State域中的值
  methods: {
    btnHandler1() {
      this.$store.commit('add');
      // this.$store.count++; // 不要在本组件中直接修改State域中数据的值
    },
    btnHandler2() {
      // commit 的作用,就是调用 某个 mutation 函数
      this.$store.commit('addN', 3)
    },
    // 异步地让 count 自增 +1
    btnHandler3() {
      // 这里的 dispatch 函数,专门用来触发 action
      this.$store.dispatch('addAsync')
    },
    btnHandler4() {
      this.$store.dispatch('addNAsync', 5)
    }
  }
}
</script>
2:触发Action方法二
  • 同样的可以使用mapActions数据结构来引入在store.js中注册过的Action和mapState、mapMutations同理。注意用mapMutations、mapActions注册过的方法可以直接根据函数名来调用。

Subtraction.vue

<template>
  <div>
    <!-- <h3>当前最新的count值为:{{count}}</h3> -->
    <h3>{{ showNum }}</h3>
    <button @click="sub">-1</button>
    <button @click="subN(3)">-N</button>
    <button @click="subAsync">-1 Async</button>
    <button @click="subNAsync(5)">-N Async</button>
  </div>
</template>

<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'

export default {
  data() {
    return {}
  },
  computed: {
    ...mapState(['count']),
  },
  methods: {
    ...mapMutations(['sub', 'subN']),
    ...mapActions(['subAsync', 'subNAsync']),
    // 注意这里的subAsync和subNAsync都可以直接作为函数被调用,不用像btnHandler1一样新开一个函数来调用
    // 由map注册过的方法都可以直接调用
    btnHandler1() {
      this.sub()
    }
  }
}
</script>

4)Getter

  • Getter用于对Store中的数据进行加工处理并形成新的数据,类似于Vue中的计算属性,Store中的数据发生变化,Getter中的数据也发生变化,存在一个响应关系。
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  // 定义唯一的state域变量
  state: {
    count: 0
  },
  mutations: {
	···
  },
  actions: {
    ···
  },
  // getter方法模拟显示当前最新的值
  getters: {
    showNum(state) {
      return '当前最新的数量是【' + state.count + '】'
    }
  }
})
1:使用getters的两种方法

在这里插入图片描述

5. Vuex综合案例

  • 详见于 vuex_demo2,里面有我非常详细的注释。
  • 注意打开新项目时应当删除module_nodes和package-lock.json两个文件夹,并输入指令npm i(即install)和npm run serve来启动服务。

相关推荐

  1. 文章vue基础(上)

    2024-03-22 14:14:02       35 阅读
  2. 文章帮你彻底剩余运算符!!

    2024-03-22 14:14:02       22 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-22 14:14:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-22 14:14:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-22 14:14:02       82 阅读
  4. Python语言-面向对象

    2024-03-22 14:14:02       91 阅读

热门阅读

  1. Python如何把PDF进行压缩分割

    2024-03-22 14:14:02       43 阅读
  2. vue3 hash和history模式路由配置

    2024-03-22 14:14:02       37 阅读
  3. 【Vue】基本知识点汇总

    2024-03-22 14:14:02       40 阅读
  4. git仓库推送和删除远程分支

    2024-03-22 14:14:02       46 阅读
  5. 【ESP32 IDF】RTC时钟

    2024-03-22 14:14:02       42 阅读