Vue3:Vuex4.x 在 Vue3 中的使用

文章详细介绍了在Vue3中如何使用新的Vuex安装和配置方法,包括使用createStore创建store,通过useStore在组合式API中访问store,以及如何访问state、getter、mutation和action。同时,文章提到了严格模式的应用,表单处理策略,以及在TypeScript环境下的支持和类型声明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前往 官方文档 查看详情。

为了与 Vue 3 初始化过程保持一致,Vuex 的安装方式已经改变了。用户现在应该使用新引入的 createStore 方法来创建 store 实例。

import { createStore } from 'vuex'

export const store = createStore({
    state () {
        return {
            count: 1
        }
    }
})

要将 Vuex 安装到 Vue 实例中,需要用 store 替代之前的 Vuex 传递给 use 方法。

import { createApp } from 'vue'
import { store } from './store'
import App from './App.vue'

const app = createApp(App)

app.use(store)

app.mount('#app')

全新的“useStore”组合式函数

Vuex 4 引入了一个新的 API 用于在组合式 API 中与 store 进行交互。可以在组件的 setup 钩子函数中使用 useStore 组合式函数来检索 store。

import { useStore } from 'vuex'

export default {
    setup () {
        const store = useStore()
        }
}

组合式API(重点)

可以通过调用 useStore 函数,来在 setup 钩子函数中访问 store。这与在组件中使用选项式 API 访问 this.$store 是等效的。

import { useStore } from 'vuex'

export default {
    setup () {
        const store = useStore()
	}
}

访问 State 和 Getter

为了访问 state 和 getter,需要创建 computed 引用以保留响应性,这与在选项式 API 中创建计算属性等效。

import { computed } from 'vue'
import { useStore } from 'vuex'

export default {
    setup () {
        const store = useStore()

        return {
            // 在 computed 函数中访问 state
            count: computed(() => store.state.count),

            // 在 computed 函数中访问 getter
            double: computed(() => store.getters.double)
        }
    }
}

访问 Mutation 和 Action

要使用 mutation 和 action 时,只需要在 setup 钩子函数中调用 commitdispatch 函数。

import { useStore } from 'vuex'

export default {
    setup () {
        const store = useStore()

        return {
            // 使用 mutation
            increment: () => store.commit('increment'),

            // 使用 action
            asyncIncrement: () => store.dispatch('asyncIncrement')
        }
    }
}

项目结构

Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:

  1. 应用层级的状态应该集中到单个 store 对象中。
  2. 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
  3. 异步逻辑都应该封装到 action 里面。

只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。

├── index.html
├── main.js
├── api
│   └── ... # 抽取出API请求
├── components
│   ├── App.vue
│   └── ...
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块

严格模式

在创建 store 的时候传入 strict: true
在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。

const store = createStore({
    strict: true
})

开发环境与发布环境

不要在发布环境下启用严格模式!严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式,以避免性能损失。

  • 类似于插件,我们可以让构建工具来处理这种情况。
const store = createStore({
    strict: process.env.NODE_ENV !== 'production'
})

表单处理

在严格模式中使用 Vuex 时,在属于 Vuex 的 state 上使用 v-model 会比较棘手,由于这个修改不是在 mutation 函数中执行的, 这里会抛出一个错误。

<input v-model="obj.message">
  • 用“Vuex 的思维”去解决这个问题的方法是:给 <input> 中绑定 value,然后侦听 input 或者 change 事件,在事件回调中调用一个方法:
<template>
	<input :value="message" @input="updateMessage">
</template>

<script>
export default {
    setup() {
        computed: {
            ...mapState({
                message: state => state.obj.message
            })
        },
		methods: {
            updateMessage (e) {
                this.$store.commit('updateMessage', e.target.value)
            }
        }
    }
}
</script>
  • mutation 函数
mutations: {
    updateMessage (state, message) {
        state.obj.message = message
    }
}
  • 双向绑定的计算属性
<template>
<input v-model="message">
</template>

<script>
export default {
    setup() {
        computed: {
            message: {
                get () {
                    return this.$store.state.obj.message
                },
				set (value) {
                    this.$store.commit('updateMessage', value)
                }
            }
        }
    }
}
</script>

TypeScript 支持

Vuex 提供了类型声明,因此可以使用 TypeScript 定义 store,并且不需要任何特殊的 TypeScript 配置。请遵循 Vue 的基本 TypeScript 配置 来配置项目。
但是,如果你使用 TypeScript 来编写 Vue 组件,则需要遵循一些步骤才能正确地为 store 提供类型声明。


Vue 组件中 $store 属性的类型声明

Vuex 没有为 this.$store 属性提供开箱即用的类型声明。如果你要使用 TypeScript,首先需要声明自定义的 模块补充(module augmentation)

  1. 项目文件夹中添加一个声明文件(vuex.d.ts)来声明 Vue 的自定义类型 ComponentCustomProperties
import { ComponentCustomProperties } from 'vue'
import { Store } from 'vuex'

declare module '@vue/runtime-core' {
    // 声明自己的 store state
    interface State {
        count: number
    }

    // 为 `this.$store` 提供类型声明
    interface ComponentCustomProperties {
        $store: Store<State>
    }
}

useStore 组合式函数类型声明

Vuex 将store 安装到 Vue 应用中使用了 Vue 的 Provide/Inject 特性,这就是 injection key 是很重要的因素的原因。

  1. 定义类型化的 InjectionKey

引入 InjectionKey 并将其传入 useStore 使用过的任何地方,很快就会成为一项重复性的工作。

  1. 将类型化的 InjectionKey 传给 useStore 方法。

通过引入自定义的组合式函数,不用提供 injection key 和类型声明就可以直接得到类型化的 store。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤安先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值