Options式Store写法
Options式Store写法
Options式Store是Vuex中传统的状态管理方式,通过定义包含state、mutations、actions等选项的对象来组织store。这种方式结构清晰,适合中小型项目或刚接触Vuex的开发者。
基本结构
一个完整的Options式Store通常包含以下几个核心部分:
const store = new Vuex.Store({
state: {}, // 状态数据
getters: {}, // 计算属性
mutations: {}, // 同步修改状态
actions: {}, // 异步操作
modules: {} // 模块化
})
State定义
State是存储应用状态的地方,建议将所有需要共享的数据集中管理:
state: {
user: {
name: '张三',
age: 28,
token: 'abc123'
},
products: [
{ id: 1, name: '商品A', price: 100 },
{ id: 2, name: '商品B', price: 200 }
],
loading: false
}
Mutations使用
Mutations是唯一能直接修改state的方法,必须是同步函数:
mutations: {
// 基本用法
SET_LOADING(state, payload) {
state.loading = payload
},
// 对象风格提交
UPDATE_USER(state, { key, value }) {
state.user[key] = value
},
// 数组操作示例
ADD_PRODUCT(state, product) {
state.products.push(product)
},
// 使用常量作为函数名
[INCREMENT_AGE](state) {
state.user.age++
}
}
Actions处理异步
Actions用于处理异步操作,最终通过commit mutations来修改state:
actions: {
// 基本异步操作
async fetchUser({ commit }, userId) {
commit('SET_LOADING', true)
try {
const user = await api.getUser(userId)
commit('SET_USER', user)
} catch (error) {
commit('SET_ERROR', error.message)
} finally {
commit('SET_LOADING', false)
}
},
// 组合多个action
async initApp({ dispatch }) {
await dispatch('fetchUser')
await dispatch('fetchProducts')
}
}
Getters计算属性
Getters可以认为是store的计算属性,适合派生状态:
getters: {
// 基本getter
totalPrice: state => {
return state.products.reduce((sum, product) => sum + product.price, 0)
},
// getter返回函数
getProductById: state => id => {
return state.products.find(product => product.id === id)
},
// 使用其他getter
discountedProducts: (state, getters) => {
return state.products.map(product => ({
...product,
discountPrice: product.price * 0.9
}))
}
}
模块化组织
当应用规模变大时,可以将store分割成模块:
const userModule = {
namespaced: true,
state: () => ({
profile: null
}),
mutations: {
SET_PROFILE(state, profile) {
state.profile = profile
}
}
}
const productModule = {
namespaced: true,
state: () => ({
list: []
}),
actions: {
loadAll({ commit }) {
// ...
}
}
}
const store = new Vuex.Store({
modules: {
user: userModule,
product: productModule
}
})
严格模式
开发环境下可以开启严格模式,防止直接修改state:
const store = new Vuex.Store({
strict: process.env.NODE_ENV !== 'production',
// ...其他配置
})
插件开发
可以通过插件扩展store功能,比如持久化插件:
const persistPlugin = store => {
// 初始化时从本地存储恢复状态
const savedState = localStorage.getItem('vuex-state')
if (savedState) {
store.replaceState(JSON.parse(savedState))
}
// 订阅mutation变化
store.subscribe((mutation, state) => {
localStorage.setItem('vuex-state', JSON.stringify(state))
})
}
const store = new Vuex.Store({
plugins: [persistPlugin],
// ...其他配置
})
与组件结合
在组件中使用mapHelpers简化store访问:
import { mapState, mapGetters, mapActions } from 'vuex'
export default {
computed: {
// 数组语法
...mapState(['user', 'products']),
// 对象语法
...mapState({
userName: state => state.user.name,
firstProduct: state => state.products[0]
}),
// getters映射
...mapGetters(['totalPrice', 'discountedProducts'])
},
methods: {
// actions映射
...mapActions(['fetchUser', 'initApp']),
// 命名空间actions
...mapActions('user', ['updateProfile'])
}
}
表单处理
处理Vuex中表单的双向绑定问题:
export default {
data() {
return {
localUser: {}
}
},
created() {
// 初始化时复制state到本地数据
this.localUser = { ...this.$store.state.user }
},
methods: {
updateUser() {
// 提交时更新state
this.$store.commit('UPDATE_USER', this.localUser)
}
}
}
测试相关
编写可测试的store代码:
// 单独导出options便于测试
export const storeOptions = {
state: { count: 0 },
mutations: {
increment(state) {
state.count++
}
},
actions: {
asyncIncrement({ commit }) {
setTimeout(() => {
commit('increment')
}, 100)
}
}
}
// 测试示例
describe('store', () => {
it('increment mutation', () => {
const state = { count: 0 }
storeOptions.mutations.increment(state)
expect(state.count).toBe(1)
})
})
类型提示
为Options式Store添加TypeScript支持:
interface State {
user: {
name: string
age: number
}
products: Array<{
id: number
name: string
price: number
}>
}
const store = new Vuex.Store<State>({
state: {
user: {
name: '',
age: 0
},
products: []
},
mutations: {
SET_USER(state: State, payload: State['user']) {
state.user = payload
}
}
})
性能优化
大型应用中优化Options式Store的技巧:
const store = new Vuex.Store({
// 使用函数返回state对象,避免模块间共享引用
state: () => ({
largeData: null
}),
// 惰性注册动态模块
modules: {
bigModule: {
namespaced: true,
// 动态导入模块定义
...import('./big-module')
}
}
})
常见模式
Options式Store中常用的设计模式:
const store = new Vuex.Store({
// 状态分组
state: {
ui: {
loading: false,
theme: 'light'
},
data: {
users: [],
products: []
}
},
// 工厂函数创建模块
modules: {
dynamicModule: createDynamicModule()
}
})
function createDynamicModule() {
return {
state: () => ({ value: 0 }),
mutations: {
increment(state) {
state.value++
}
}
}
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:组合式Store写法
下一篇:Store间相互调用