第11天:状态管理VueX

VueX介绍

VueX简单介绍

  • 对于组件化开发来说,大型应用的状态往往跨越多个组件。在多层嵌套的父子组件之间传递状态已经十分麻烦,而Vue更是没有为兄弟组件提供直接共享数据的办法。
  • 基于这个问题,许多框架提供了解决方案——使用全局的状态管理器,将所有分散的共享数据交由状态管理器保管,Vue也不例外。
  • Vuex 是一个专为 Vue.js 应用程序开发的状态管理库,采用集中式存储管理应用的所有组件的状态。
  • 简单的说,Vuex用于管理分散在Vue各个组件中的数据。
  • VueX安装:npm install vuex@next(安装最新版本)

状态管理

  • vuex使用在比较复杂的网站开发,并不是必须的。
  • 每一个Vuex应用的核心都是一个store(vuex里面统一的实例,全局对象,所有组件要共享的数据都可以存储在store内部,由他进行维护和管理),与普通的全局对象不同的是,基于Vue数据与视图绑定的特点,当store中的状态发生变化时,与之绑定的视图也会被重新渲染(store与视图进行绑定)。
  • store中的状态不允许被直接修改,改变store中的状态的唯一途径就是显式地提交(commit)mutation,这可以让我们方便地跟踪每一个状态的变化(便于维护)。
  • 在大型复杂应用中,如果无法有效地跟踪到状态的变化,将会对理解和维护代码带来极大的困扰。
  • Vuex中有5个重要的概念:State、Getter、Mutation、Action、Module。
    在这里插入图片描述
    如果有异步请求,通过Dispatch触发Action,Action提交Mutation,最终修改State里面的数据;如果没有异步操作,也可以组件直接提交Mutation,进而修改State里面的值。
    Vuex中5个重要概念的使用流程介绍:
    以下代码基于vue3,即vuex4
    1. State
      State用于维护所有应用层的状态,并确保应用只有唯一的数据源
      在这里插入图片描述
      在组件中,可以直接使用this.$store.state.count访问数据,也可以先用mapState辅助函数将其映射下来
      在这里插入图片描述
    2. Getter
      Getter维护由State派生的一些状态,这些状态随着State状态的变化而变化(比如State里面存储一些待办事项,如果完成为真,没有完成为假,在这个界面可能想显示所有已完成的,或者显示所有未完成的)
      在这里插入图片描述
      在组件中,可以直接使用this.$store.getters.doneTodos,也可以先用mapGetters辅助函数将其映射下来,代码如下:
      在这里插入图片描述
    3. Mutation
      Mutation提供修改State状态的方法。
      在这里插入图片描述
      在组件中,可以直接使用store.commit来提交mutation
      在这里插入图片描述
      也可以先用mapMutation辅助函数将其映射下来
      在这里插入图片描述
    4. Action
    • Mutation里面只能做一些同步的操作,为了追踪状态的变化,如果是一些异步的操作,使用Action

    • Action类似Mutation,不同在于:Action不能直接修改状态,只能通过提交mutation来修改,Action可以包含异步操作。

    • Action里面定义的也是方法,参数是contex(上下文对象),不是直接修改状态,而是提交mutation。(比如网络请求获取的数据需要更新State里面的数据,使用context提交mutation,进而间接修改State里面的数据,之所以这样设计,是为了能在Action里面记录State的变化)
      在这里插入图片描述

      在组件中,可以直接使用this.$store.dispatch(‘xxx’)分发 action,或者使用mapActions辅助函数先将其映射下来
      在这里插入图片描述

VueX安装与使用

VueX安装

方法一
在创建vue项目时选中vuex模块进行安装
在这里插入图片描述
方法二
使用npm install进行安装

vue2: npm install vuex@3
vue3: npm install vuex@4

VueX 使用

VueX使用关于State

src/store/index.js

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

Vue.use(Vuex)

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

main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store'

Vue.config.productionTip = false

new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

HelloWorld.vue

<template>
  <div class="hello">
      {{ this.$store.state.count }}
      <button @click="add">+1</button>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  methods:{
    add(){
      // this.$store.state.count = this.$store.state.count +1
      this.$store.commit("increment")
    }
  }
  
}
</script>

HelloWorld.vue更简便写法
在这里插入图片描述
或者
使用mapState辅助函数
在需要使用的组件中进行导入:

import { mapState } from 'vuex'

修改computed部分(以下三种方式均可):

 computed: mapState({
    // 箭头函数可使代码更简练
    count: state => state.count,

    // 传字符串参数 'count' 等同于 `state => state.count`
    countAlias: 'count',

    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })

当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。

computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])

VueX使用关于Getter

src/store/index.js
在这里插入图片描述
使用mapGetters,代码示例:
HelloWorld.vue

<template>
  <div class="hello">
      <!-- {{ this.$store.state.count }} -->
      {{ count }}
      <button @click="add">+1</button>

      <!-- Getter -->
      <ul>
      <li v-for="todo in doneTodos" :key="todo.id">{{ todo.text }}</li>
    </ul>
  </div>
</template>
<script>
import { mapState,mapGetters } from 'vuex'
export default {
  name: 'HelloWorld',
  //mapState与mapGetters同时使用
  computed:{
      ...mapState([
    'count','todos'
      ]),
      ...mapGetters([
          'doneTodos'
      ])
  },
  methods:{
  add(){
    // this.$store.state.count = this.$store.state.count +1
    this.$store.commit("increment")
  }
}
  
}
</script>

VueX使用关于Mutation

可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload):
src/store/index.js

mutations: {
        // increment(state) {
        //     state.count++
        // }
        increment(state, n) {
            state.count += n
        }
    },

HelloWorld.vue

methods:{
  add(){
    // this.$store.state.count = this.$store.state.count +1
    this.$store.commit("increment",2)
  }
}

可以在组件中使用 this.$store.commit(‘xxx’) 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。

import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`

      // `mapMutations` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
    ]),
    ...mapMutations({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
  }
}

VueX使用关于Action

之所以要抽象出Action,是为了记录异步数据的状态变化
注册一个简单的Action
src/store/index.js

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

分发Action
Action 通过 store.dispatch 方法触发:

store.dispatch('increment')

在组件中分发 Action
在组件中使用 this.$store.dispatch(‘xxx’) 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store):

HelloWorld.vue

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}

VueX使用关于Module

如果应用数据特别多,vue允许分割模块。
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

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 的状态
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值