vuex 4 版本学习笔记

928 阅读2分钟

vuex 4 安装

几乎所有的 Vuex 4 API 都与 Vuex 3 保持不变。但是,仍有一些非兼容性变更需要注意

yarn add vuex@next -- save

src 目录下新建 store/index.js

import { createStore } from 'vuex'

// 创建一个新的 store 实例
const store = createStore({
  state () {
    return {
      count: 0
    }
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

export default store

在main.js中引入store,并引用

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

import router from './router'
import store from './store'

createApp(App)
  .use(router)
	.use(store)
  .mount('#app')

现在,可以通过 store.state 来获取状态对象,并通过 store.commit 方法触发状态变更:

store.commit('increment')

console.log(store.state.count) // -> 1

组合式API

在 Vue 组件中, 传统写法是通过 this.$store 访问store实例

在vue3中则是通过调用 useStore 函数,这与在组件中使用选项式API访问 this.$store 是等效的

<template>
	<!-- 传统写法 -->
	<p @click="$store.commit('increment')">{{ $store.state.count }}</p>

	<!-- composition写法 -->
	<p @click="increment()">{{ state.count }}</p>
</template>

<script setup>
  import { useStore } from "vuex"

  const store = useStore()
  
  const state = store.state
  function increment() {
  	store.commit('increment')
  }

</script>

访问 State 和 Getter

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

<script setup>
  import { computed } from 'vue'
  import { useStore } from 'vuex'

	const store = useStore()
  // 在computed函数中访问state
  const count = computed(() => store.state.count)
  // 在computed函数中访问getter
  const double = computed(() => store.getters.double) 
  // 通过 ...toRefs解构state为响应式
  const { count } = {...toRefs(store.state)}
</script>

访问 Mutation 和 Action

要使用 mutation 和 action 时,只需要调动 commit 和 dispatch 函数

<script setup>
	import { useStore } from 'vuex'
  
  const store = useStore()
  // 使用mutation
  const increment = (x, y) => store.commit('increment', {x, y})
  // 使用action
  const asyncIncrement = x => store.dispatch('asyncIncrement', x)
  
</script>

严格模式

开启严格模式

仅需在创建 store 的时候传入 strict: true

const store = createStore({
  // ...
  strict: true
})

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

不要在发布环境下启用严格模式!

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

类似于插件,我们可以让构建工具来处理这种情况:

const store = createStore({
  // ...
  strict: process.env.NODE_ENV !== 'production'
})

表单处理

在严格模式中,v-model 修改 state 会比较棘手

<input v-model="obj.message">

如果obj.message 是一个字计算属性中返回的一个 Vuex store 对象,在用户输入时,v-model 会试图直接修改 obj.message,在严格模式中,由于状态修改不是通过mutation提交的,严格模式下就会抛出错误

改为事件触发提交

用vuex的思维去解决这个问题的方法,便是不采用v-model方式,而是给 绑定 value,然后侦听 input 或者 change 事件,在事件中向mutation提交

<template>
	<input :value="message" @input="updateMessage">
</template>

<script setup>
	import { computed } from 'vue'
  import { useStore } from 'vuex'
  
  const store = useStore()
  const message = computed(() => store.state.message)
  const updateMessage = e => store.commit('updateMessage', e.target.value)
</script>

下面是mutation函数

// ...
mutations: {
  updateMessage (state, message) {
    state.obj.message = message
  }
}

双向绑定的及计算属性

上面的方法比简单地使用“v-model + 局部状态”要啰嗦得多,并且也损失了一些 v-model 中很有用的特性。另一个方法是使用带有 setter 的双向绑定计算属性:

<template>
	<input v-model="message">
</template>

<script setup>
	import { useStore } from 'vuex'
  
  const store = useStore()
  
  const message = computed({ //xxxxxxx有问题
    get() {
      return store.state.obj.message
    },
    set(value) {
      store.commit('updateMessage', value)
    },
  })
</script>