2021-06-23vuex - 第七天

一、vuex

1. 概念

Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。

① 能够在 vuex 中集中管理共享的数据,易于开发和后期维护
② 能够高效地实现组件之间的数据共享,提高开发效率
③ 存储在 vuex 中的数据都是响应式的,能够实时保持数据与页面的同步

一般情况下,只有组件之间共享的数据,才有必要存储到 vuex 中;对于组件中的私有数据,依旧存储在组件自身的 data 中即可。

2. 不使用脚手架,在项目中配置vuex

(1)安装 vuex 依赖包

npm install vuex --save

(2)在 store.js 文件中导入 vue 和 vuex。全局注册vuex。

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

全局注册vuex: Vue.use(Vuex)

(3) 在 store.js 文件中创建 store 对象

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

(4)在main.js中导入store.js ,并将 store 对象挂载到 vue 实例中

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

二、 vuex的核心属性

注意:
(1)在 组件 中可以用 $store 调用store中的数据和方法。
(2)在普通的 js文件 中需要用 import 导入 vuex文件,才能使用其中的数据。
(3)用脚手架创建项目后,在vuex文件中创建vuex的实例对象store

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {
    // 子模块users
    users: {
     namespaced: true
      state: {},
      mutations: {},
      actions: {},
      getters: {}
    },
    // 子模块settings
    settings: {
      namespaced: true
      state: {},
      mutations: {},
      actions: {},
      getters: {}
    }
  }
})

1. state

所有 共享的数据 都要统一放到 vuex的实例对象store 的 state 中进行存储。

(1)将数据存放到 state 中。
(2)在组件中调用 state 数据的第一种方法:直接在组件中获取state数据

this.$store.state.数据名称

(3)在组件中调用 state 数据的第二种方法:将state数据映射为本组件的计算属性。

① 首先在组件中导入vuex 提供的 mapState 函数

import { mapState } from 'vuex'

② 使用mapState方法将 state 中的数据映射为本组件的 计算属性

export default {
 computed: {
   ...mapState(['数据名称'])
 }
}

2. mutations

只有 mutations 中的方法,才能真正操作 state 中的数据。

(1)在 mutations 中定义方法,每个方法的第一个参数都是 state。通过参数state,可以得到state 中的数据进行操作。第二个参数往后都是自定义参数

mutations: {
  addOne (state, tempNum) {
  state.count += tempNum
  },
},

(2)在组件中操作 state 数据的第一种方法:直接在组件中获取mutations方法

this.$store.commit('mutations方法名称', 自定义参数)

注意:如果需要传递多个参数,请使用对象或者数组一次性传递过来。

(3)在组件中操作 state 数据的第二种方法:将mutations方法映射为本组件的方法。

① 首先在组件中导入vuex 提供的 mapMutations 函数

import {mapMutations } from 'vuex'

② 使用mapMutations函数将 mutations 中的方法映射为本组件的方法。

methods: {
...mapMutations([ 'mutations方法名' ]),
}

3. action

  • 异步操作都存放在 action 中。
  • 但是,只有 mutations 才能真正操作state 数据。
  • 所以,action 中的异步函数要调用 mutations 中的方法,来实现异步地操作state数据。
  • actions中的方法大多用 async 标记成异步函数了,组件调用时要用async 和 await 标记。

(1) 在 action 中定义异步函数,并在函数内部调用 mutations 中的方法。

每个异步函数的第一个参数都是 context,通过 context.commit( 'mutations方法名',自定义参数) 可以调用 mutations 中的方法。

actions: {
 addAsync (context, tempNum) {
   setTimeout(() => {
    context.commit(' addOne ', tempNum)
  }, 1000)
 },
},

(2)在组件中异步地操作state数据的第一种方法:直接在组件中调用action的异步函数。

this.$store.dispatch('action方法名', 自定义参数)

(3)在组件中异步地操作state数据的第二种方法:将action方法映射为本组件的方法。

① 首先在组件中导入vuex 提供的 mapActions 函数

import {mapActions } from 'vuex'

② 使用mapActions函数将 actions 中的方法映射为本组件的方法

methods: {
...mapActions([ 'mutations方法名' ]),
}

4. getters

① vuex中的getters 与 vue中的 计算属性 类似。
② 除了state之外,有时我们还需要从state中派生出一些状态,这些状态是依赖state的,此时会用到getters.
③ 在 getters 中定义方法,每个方法的 第一个参数都是 state
④ getters中的函数必须有返回值。getters函数在组件中被当做 state数据 使用。

getters: {
  filterList (state) {
  return state.list.filter(item => item > 5)
  },
},

(1)直接在组件中使用vuex中的getters

this.$store.getters.方法名

(2)将vuex的getters映射为组件的计算属性

① 在组件中导入vuex提供的 mapGetters 放法

import {mapGetteers } from 'vuex'

② 利用mapGetters方法,将getters映射为组件的计算属性。

computed: {
   ...mapGetters(['方法名称'])
 }

三、vuex的模块化

vuex中的第五个 核心属性modules,可以创建子模块vuex。

1. 在组件中使用vuex子模块的 state 数据

方法一: 直接在组件中调用

this.$store.state.vuex子模块名称.数据名称

<div>{{$store.state.users.name}}</div>

方法二:将vuex子模块中的数据,包装为全局getters。组件调用全局的getters。

全局getters属性:
getters:{
自定义名称:(state)=>{ return state.子模块名称.数据名称 }
}

getters: {
    usersName: (state) => {
      return state.users.name
    }
  }

方法三:在组件中使用mapState方法,映射为组件的计算属性。

computed:{ ...mapState("vuex模块名称",[])}
注:uniapp小程序中学的

computed:{
      ...mapState('Cart',['name'])
    },
2.在组件中调用vuex子模块的 mutations方法

① 默认情况下,子模块的mutations方法被注册到了全局的vuex上。组件可以通过this.$store.commit.方法名 调用。
② 但这不符合模块化的封装,所以,要给每个vuex子模块添加属性:namespaced:true

方法一:直接在组件中调用--带上子模块名称

this.$store.commit( "vuex子模块名称 / 方法名称" ,实参)

this.$store.commit('users/changeName', '马冬梅')

方法二:mapMutations函数映射--方法名前面要加子模块名称。

methods: {
  ...mapMutations(['子模块名称 / 方法名']),
 test () {
    this['子模块名称 / 方法名'] ()
  }
}

也可以写成:...mapMutations("子模块名称",["方法名"])
注:uniapp小程序中学的

方法三:使用 createNamespacedHelpers 创建基于某个命名空间辅助函数

import { mapGetters, createNamespacedHelpers } from 'vuex'
const { mapMutations } = createNamespacedHelpers('子模块名称')

组件中添加了这两行代码,就可以在methods中映射指定子模块的mutations方法了。

四、vuex兄弟子模块之间方法的调用

① 上面已经详细说明了如何在 vue组件中调用 vuex的数据和方法

② 但是,两个添加了namespaced命名空间的 vuex子模块,不能相互使用其中的数据和方法。因为添加了命名空间后,子模块的state、context只能拿到当前模块的数据和方法。

在子模块A的actions中调用子模块B的mutations方法:
context.commit(" 模块名称/mutations方法名称" , [], { root: true })

五、同一子模块的mutations方法的相互调用

理论上来说,使用this.commit('函数 ')即可调用另一个Mutations方法。
但是在开启命名空间的子模块中,使用 this.commit(’ 模块名/函数 ') 的方法来调用。即便是在同一个模块下,Mutations中的其中一个方法回调另一个方法时,也需要用 this.commit(’ 模块名/函数 ') 的方式来调用。

this.commit("子模块名/函数 ")

六、 vuex实际应用

1.该组件使用state数据、mutations方法、actions方法时,都是直接调用。

<template>
  <div>
    <!-- 组件内使用state中的数据  方法一 -->
    <div>vuex中的数据count值为:{{$store.state.count}}</div>
    <button @click="handler1">+1</button>
    <button @click="handler2">+5</button>
  </div>
</template>

<script>
export default {
  methods: {
    // 组件内操作state中的数据  方法一
    handler1 () {
      this.$store.commit('addOne', 1)
    },
    // 组件内异步地操作state中的数据 方法一
    handler2 () {
      this.$store.dispatch('addAsync', 5)
    }
  }
}
</script>

<style scoped>
</style>

2.这是vuex文件。

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

Vue.use(Vuex)

const store = new Vuex.Store({
  // 存储公有数据
  state: {
    count: 0
  },

  // 存放更改公有数据的方法
  mutations: {
    // 加一
    addOne (state, tempNum) {
      state.count += tempNum
    },

    // 减一
    subOne (state, tempNum) {
      state.count -= tempNum
    }
  },

  // 存放异步方法
  actions: {
    // 异步加5
    addAsync (context, tempNum) {
      setTimeout(() => {
        context.commit('addOne', tempNum)
      }, 1000)
    },

    // 异步减5
    subAsync (context, tempNum) {
      setTimeout(() => {
        context.commit('subOne', tempNum)
      }, 1000)
    }
  },
  modules: {
  }
})

export default store

3.该组件使用state数据、mutations方法、actions方法时,都是映射到本组件内再使用。

<template>
  <div>
    <div>{{count}}</div>
    <button @click="handler1">-1</button>
    <button @click="handler2">-5</button>
  </div>
</template>

<script>
// 导入 vuex 提供的 【mapState】方法
// 导入 vuex 提供的 【mapMutations】方法
// 导入 vuex 提供的 【mapActions】方法
import { mapState, mapMutations, mapActions } from 'vuex'

export default {
  // 组件内使用state数据 方法二
  computed: {
    ...mapState(['count'])
  },

  methods: {
    // 组件内操作state数据 方法二
    ...mapMutations(['subOne']),
    handler1 () {
      this.subOne(1)
    },

    // 组件内异步地操作state数据 方法二
    ...mapActions(['subAsync']),
    handler2 () {
      this.subAsync(5)
    }
  }
}
</script>

<style scoped>
</style>

补充:

  1. 一个对象调用它的属性时的三种方法:

对象名.属性名
对象名[ "属性名" ]
对象名[ 变量名 ],其中变量的值等于属性名

平常使用变量,用的是变量名;但只要给 变量 加上 [ ],就代表获取变量值。
例如:

      var a = 10
      console.log({ a: '猜猜a是什么' }) // { a: '猜猜a是什么' }
      console.log({ [a]: '猜猜a是什么' }) // { 10: '猜猜a是什么' }
  1. vuex中的数据响应式
    只修改数组或对象的元素、属性,不具有数据的响应式效果。
    也就是必须给数组或对象赋值替代,才能在改变数据时让页面也同步变化。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容