阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > Options式Store写法

Options式Store写法

作者:陈川 阅读数:34957人阅读 分类: Vue.js

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间相互调用

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌