【Vuex入门】——(四)Mutation

2023-11-12

一、Mutation的作用

更改 Vuexstore 中的状态的唯一方法是提交 mutation


Vuex 中的 mutation 非常类似于事件:

  • 每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。

  • 这个回调函数就是我们实际进行状态更改的函数,并且它会接受 state 作为第一个参数

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
  	// 第一个参数为 state
    add(state) {
      // 变更状态,即变更值
      state.count++
    }
  }
})
  • 你不能直接调用一个 mutation handler

这个选项更像是事件注册:

“当触发一个类型为 addmutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:

store.commit('increment')

二、提交载荷(Payload)

即当我们想修改状态值,想传入的值进而进行修改时,你可以向 store.commit 传入额外的参数,即 mutation载荷(payload)

// 定义
mutations: {
  // n被称为载荷, 即为我们传入的值
  add(state, n) {
    state.count += n
  }
}
// 调用
store.commit('increment', 10)

在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读:

// 定义
mutations: {
  add(state, payload) {
    state.count += payload.amount
  }
}
// 调用
store.commit('increment', {
  amount: 10
})

三、对象风格的提交方式

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

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

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

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

四、Mutation 需遵守 Vue 的响应规则

最好提前在你的 store 中初始化好所有所需属性。

若需要在对象上添加新属性时,你应该:

  • 使用 Vue.set(obj, 'newProp', 123)
  • 以新对象替换老对象。例如,利用对象展开运算符我们可以这样写:
state.obj = { ...state.obj, newProp: 123 }

五、Mutation 必须是同步函数 !!!

一条重要的原则就是要记住 mutation 必须是同步函数。为什么?请参考下面的例子:

mutations: {
  someMutation (state) {
     // 一秒后count++
    setTimeout(() => {
      state.count++
    }, 1000)
  }
}

现在想象,我们正在 debug 一个 app 并且观察 devtool 中的 mutation 日志。每一条mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用——实质上任何在回调函数中进行的状态的改变都是不可追踪的。
即虽然1秒后我们可以实现 state.count++ ,但是 devtools 是无法监测state.count 的改变的。 假设调用通过 someMutation count 的值为0, 打开 devtools工具,然后我们调用 someMutation ,观察 devtools 的记录,我肯可以看到 devtools 监听到的 count 的值还是为0, 因为时异步函数,所以 someMutationstate.count++ 操作还没有执行。 大家可以尝试在自己的浏览器使用 devtools 工具试试看。

六、在组件中提交 Mutation

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

// main.js
// 根节点引入store
new Vue({
  el: '#app',
  store
})
// 组件

// 引入辅助函数 mapMutations 
import { mapMutations } from 'vuex'

export default {
  methods: {
    // 将 `this.add()` 映射为 `this.$store.commit('add')`
    // `mapMutations` 也支持载荷:
    // 将 `this.addBy(amount)` 映射为 this.$store.commit('addBy', amount)`
    ...mapMutations(['add', 'addBy']),
    // 将 `this.increment()` 映射为 `this.$store.commit('add')`
    ...mapMutations({
      increment: 'add' 
    })
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Vuex入门】——(四)Mutation 的相关文章

  • 我可以动态创建/销毁 Vue 组件吗?

    因此 我正在创建一个相当复杂的 Vue 应用程序 它从后端 API 获取数据并将其显示在前端 具体取决于用户选择的过滤器 它的默认设置是立即显示所有内容 然后一旦用户选择过滤器 它就会拉出不具有这些属性的 卡片 组件 直到今天 一切都很顺利
  • 如果用户在 Laravel 中经过身份验证,如何检查 Vue 组件?

    正如标题所述 我有点困惑如何根据用户是否登录并使用 Laravel 的 Auth 外观进行身份验证 使用 if else 语句处理 Vue 组件中的方法 我正在发出各种 Axios 请求 我需要根据用户是否登录来允许 禁止这些请求 我有 V
  • 构建 Vue 微前端应用程序(带有路由和 vuex 存储)

    我需要帮助配置使用 Vuex Vue Router 和 Vue i18n 的微前端应用程序的构建 分发 TL DR 我在构建将导入到现有系统中的微前端应用程序时遇到问题 我们的团队尝试通过 vue cli service 和 vue web
  • 在 Angular 中使用 Vue 组件

    我有一个用 Vue 构建的项目 我想在 Angular 应用程序中重用 Vue 应用程序中的组件 这样我就不必从头开始重建每个组件 我在medium上看到了这个教程 如何在 Angular 应用程序中使用 Vue 2 0 组件 https
  • v-file-input .click() 不是函数

    我试图以编程方式触发 v file input 的 click 事件 因为它在 Vuetify 的文档中 但它显示一个错误this refs imagePicker click is not a function我在这里错过了什么吗 代码重
  • Eslint 状态已声明 [Vuex]

    我正在运行 ESLint 目前遇到以下 ESLint 错误 错误 状态 已在上部范围无阴影中声明 const state date show false const getters date state gt state date show
  • 通过 declarativeNetRequest + extensionPath 重定向时获取原始 URL

    我需要在导航时但在用户从使用设置的规则重定向之前获取 chrome 选项卡的 urldeclarativeNetRequest 目前 用户可以使用上下文菜单添加规则 当尝试访问过滤的主机时 它将被重定向到内部扩展页面 chrome cont
  • Vue.js + Element UI:在更改时获取“event.target”

    我无法获取在事件处理程序中触发事件的 html 字段 在 javascript 中是event target 我有一个表格 附加到更改事件函数的输入元素 管理更改事件的函数 我的代码如下 var Main methods change pa
  • 使用 nuxt/content 显示从数据库获取的 markdown

    我在我的应用程序中使用 nuxt content 它工作正常 在应用程序的另一部分 我想从数据库中获取一些降价并显示它 let mytext Some markdown fetched from a db here
  • vue-chartjs 反应数据错误

    我正在尝试使用反应式数据混合vue chartjs http vue chartjs org home id reactive data 用于设置初始数据的已安装函数正在运行 我可以使用 API 响应正确查看图表 fetchSessionT
  • vue如何设置嵌套对象的默认道具

    我的道具是这样的 house kitchen sink 我尝试过类似的事情 但没有成功 props house type Object default gt kitchen sink 如何为此类对象设置默认道具 来自文档 对象或数组默认值必
  • nuxt中根据url参数动态加载组件

    我在 nuxt 中有一个页面 分为两部分 第一部分是一个普通的模板结构 填充了基于 url 参数的动态内容 第二部分是应根据此数据加载的组件 我正在尝试这样完成它
  • 在 Vue SFC 组件中导入 SCSS 文件,无需使用 Webpack 进行重复

    当我尝试访问所有 Vue SFC 中的 scss 文件时 样式会重复 导致大型 css 包和开发工具在样式调试时崩溃 我正在使用 Webpack 4 和 webpack dev server 来构建和运行具有热重载的开发服务 我没有使用 V
  • 在 vuejs 上将 \n 替换为新行

    我正在尝试将 n 字符替换为来自端点的数据的新行 I tried p item licensedocument legal documentText replace r n r n g br p 并没有奏效 当我将replace 写入问题末
  • Vue: vue-i18n: 无法翻译 keypath 的值,使用 keypath 的值作为默认值

    我正在使用 Vue 我想展示三种语言 英语 他加禄语和宿务语 现在我有错误 无法转换键路径 NavbarMobile home 的值 使用 keypath 的值作为默认值 我通过 console log this i18n locale 检
  • Cytoscape 布局 - 处理锁定节点

    我正在使用 vue cytoscape 渲染图形并浏览树状数据结构 我的目标是扩展父节点并保持它们在图中的位置 我想简单地添加新的子节点 我的方法是锁定当前节点 添加子节点并解锁节点 this cy nodes lock for let d
  • 如何在vuetify中设置固定工具栏?

    在 vuetify 中我使用工具栏
  • Vue.js - 当标头中使用 multipart/form-data 时,axios 中的文件上传验证失败

    我正在构建一个 Laravel Vue js SPA 单页应用程序 BootstrapVue https bootstrap vue js org Vee验证 https logaretm github io vee validate gu
  • Nuxt JS 插件是否可以只运行一次?

    我有几个 VueX 操作 仅在服务器上运行 并从nuxtServerInit 它们向外部服务发出 HTTP 请求 这会减慢 TTFB 的速度 我想实现一个缓存插件 可以从 Redis 存储和检索值 目的是避免在每个请求的操作中发出 HTTP
  • 如何在 ChartJS 中创建自定义图例

    我需要使用 ChartJS 库为我的圆环图创建自定义图例 我已经使用 ChartJS 提供的默认图例创建了甜甜圈 但我需要一些修改 我希望其价值高于汽车名称 另外 我不喜欢粘性图例 我想将其与甜甜圈分开 这样我就可以更改字体 框的样式 例如

随机推荐