面试官:请你说一说vuex的五个属性,分别是什么,区别和用途说一下(二)

简介: 面试官:请你说一说vuex的五个属性,分别是什么,区别和用途说一下

面试官:请你说一说vuex的五个属性,分别是什么,区别和用途说一下(一)https://developer.aliyun.com/article/1429046


mutations对象风格的提交方式

提交 mutation 的另一种方式是直接使用包含 type 属性的对象:

store.commit({
  type: 'increment',
  amount: 10
})

当使用对象风格的提交方式,整个对象都作为载荷传给 mutation 函数,因此 handler 保持不变:

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

你可以在组件中使用 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({
      add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
    })
  }
}

actions

action 类似于 mutation,不同在于:

  • action 提交的是 mutation,而不是直接变更状态。
  • action 可以包含任意异步操作。

vuex 里面 actions 只是一个架构性的概念,并不是必须的,本质上就是一个函数,你在里面想干嘛都可以,可以通过异步方式执行各种任务,要修改state数据还是需要通过commit触发 mutation 。

可以把mutation比作仓库的管理员,负责仓库管理,而把action比作领导,可以命令仓库管理员作操作,但不会亲自动手。

注册一个简单的 action:

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

actions 的第一个参数是 context,它向外暴露一组与 store 实例相同的方法/属性,所以可以直接调用 context.commit 或者访问 context.state 或者 context.getters 。我们通常使用 es6 的参数解构来简化我们的代码,直接写成{ commit }

actions: {
  increment ({ commit }) {
    commit('increment')
  }
}

Action 通过 store.dispatch 方法触发:

  • store.dispatch(‘increment’)

乍一眼看上去感觉多此一举,我们直接分发 mutation 岂不更方便?实际上并非如此,还记得 mutation 必须同步执行这个限制么?Action 就不受约束!我们可以在 action 内部执行异步操作:

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

Actions 支持同样的载荷方式和对象方式进行分发:

  • 以载荷形式分发
store.dispatch('incrementAsync', {
  amount: 10
})
  • 以对象形式分发
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

在组件中分发 Action

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

import { mapActions } from 'vuex'
export default {
  // ...
  methods: {
    ...mapActions([
      'increment' // 映射 this.increment() 为 this.$store.dispatch('increment')
    ]),
    ...mapActions({
      add: 'increment' // 映射 this.add() 为 this.$store.dispatch('increment')
    })
  }
}

组合 Actions

Action 通常是异步的,那么如何知道 action 什么时候结束呢?更重要的是,我们如何才能组合多个 action,以处理更加复杂的异步流程?

第一件事你需要清楚的是 store.dispatch 的返回的是被触发的 action 函数的返回值,因此你可以在 action 中返回 Promise:

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

现在你可以:

store.dispatch('actionA').then(() => {
  // ...
})

在另外一个 action 中也可以:

actions: {
  // ...
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}

最后,如果我们利用 [async / await] 这个 JavaScript 即将到来的新特性,我们可以像这样组合 action:

假设 getData() 和 getOtherData() 返回的是 Promise

actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}

Modules

使用单一状态树,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store 对象会变得臃肿不堪。

为了解决以上问题,Vuex 运行我们将 store 分割到多个模块(module)。每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}
onst moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}
const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

模块的局部状态

对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态。

const moduleA = {
  state: { count: 0 },
  mutations: {
    increment: (state) {
      // state 模块的局部状态
      state.count++
    }
  },
getters: {
    doubleCount (state) {
      return state.count * 2
    }
  }
}

同样,对于模块内部的 action,context.state 是局部状态,根节点的状态是 context.rootState:

const moduleA = {
  // ...
  actions: {
    incrementIfOdd ({ state, commit }) {
      if (state.count % 2 === 1) {
        commit('increment')
      }
    }
  }
}

对于模块内部的 getter,根节点状态会作为第三个参数:

const moduleA = {
  // ...
  getters: {
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}


面试官:请你说一说vuex的五个属性,分别是什么,区别和用途说一下(三)https://developer.aliyun.com/article/1429055

相关文章
|
1月前
|
消息中间件 负载均衡 Kafka
【Kafka面试演练】那Kafka消费者手动提交、自动提交有什么区别?
嗯嗯Ok。分区的作用主要就是为了提高Kafka处理消息吞吐量。每一个topic会被分为多个分区。假如同一个topic下有n个分区、n个消费者,这样的话每个分区就会发送消息给对应的一个消费者,这样n个消费者负载均衡地处理消息。同时生产者会发送消息给不同分区,每个分区分给不同的brocker处理,让集群平坦压力,这样大大提高了Kafka的吞吐量。面试官思考中…
70 4
|
2月前
|
存储 安全 关系型数据库
|
1月前
|
编译器 C++ Python
【C/C++ 泡沫精选面试题02】深拷贝和浅拷贝之间的区别?
【C/C++ 泡沫精选面试题02】深拷贝和浅拷贝之间的区别?
33 1
|
20天前
|
Java 关系型数据库 MySQL
大厂面试题详解:Java抽象类与接口的概念及区别
字节跳动大厂面试题详解:Java抽象类与接口的概念及区别
40 0
|
25天前
|
存储 JSON Java
面试官:Session和JWT有什么区别?
JSON Web Token (JWT) 是一种开放标准,用于安全地在网络上传输信息。JWT 包含头部、载荷和签名三部分,常用于身份验证和授权。与Session相比,JWT有以下优势:无服务器存储状态,支持跨域,适应微服务架构,自包含且可扩展。在Java开发中,可以使用HuTool框架操作JWT,包括生成、验证和解析Token。JWT通过在客户端存储令牌实现无状态认证,与Session的主要区别在于工作原理、存储方式和有效期管理。
32 6
|
1月前
|
消息中间件 算法 Java
面试官:Kafka和ES选主有什么区别?
Kafka 和 ES,作为大数据处理的中间件,分别用于流处理和全文检索。它们的选主(Kafka 的 Controller 和 ES 的 Master)都基于 Raft 算法实现一致性。Raft 算法通过选举确保分布式系统数据一致性,涉及领导者、追随者和候选人间的身份转换。当超过一半的节点投票给同一候选节点时,该节点成为新领导者。Kafka 和 ES 在此基础上可能有各自优化调整。更多关于 Raft 算法的详细流程和选举规则见原文。
44 2
|
1月前
|
网络协议 网络性能优化
网络面试题:TCP和UDP的区别
网络面试题:TCP和UDP的区别
25 0
|
1月前
|
监控
嵌入式面试题:数据传输单工,半双工,全双工之间的区别
嵌入式面试题:数据传输单工,半双工,全双工之间的区别
14 0
|
1月前
|
运维 负载均衡 NoSQL
【大厂面试官】知道Redis集群和Redis主从有什么区别吗
集群节点之间的故障检测和Redis主从中的哨兵检测很类似,都是通过PING消息来检测的。。。面试官抓抓脑袋,继续看你的简历…得想想考点你不懂的😰。
67 1
|
1月前
|
存储 C语言
c语言中strlen与sizeof的区别(指针面试题详解帮你深度区分!)
c语言中strlen与sizeof的区别(指针面试题详解帮你深度区分!)