Options-style Store writing
Options-style Store Writing
The Options-style Store is the traditional state management approach in Vuex, organizing the store by defining an object containing options such as state, mutations, and actions. This method offers a clear structure and is suitable for small to medium-sized projects or developers new to Vuex.
Basic Structure
A complete Options-style Store typically includes the following core parts:
const store = new Vuex.Store({
state: {}, // State data
getters: {}, // Computed properties
mutations: {}, // Synchronous state modifications
actions: {}, // Asynchronous operations
modules: {} // Modularization
})
State Definition
State is where the application's state is stored. It is recommended to centralize all shared data:
state: {
user: {
name: 'Zhang San',
age: 28,
token: 'abc123'
},
products: [
{ id: 1, name: 'Product A', price: 100 },
{ id: 2, name: 'Product B', price: 200 }
],
loading: false
}
Mutations Usage
Mutations are the only way to directly modify the state and must be synchronous functions:
mutations: {
// Basic usage
SET_LOADING(state, payload) {
state.loading = payload
},
// Object-style commit
UPDATE_USER(state, { key, value }) {
state.user[key] = value
},
// Array operation example
ADD_PRODUCT(state, product) {
state.products.push(product)
},
// Using constants as function names
[INCREMENT_AGE](state) {
state.user.age++
}
}
Actions for Asynchronous Handling
Actions are used for asynchronous operations and ultimately modify the state by committing mutations:
actions: {
// Basic asynchronous operation
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)
}
},
// Combining multiple actions
async initApp({ dispatch }) {
await dispatch('fetchUser')
await dispatch('fetchProducts')
}
}
Getters as Computed Properties
Getters can be considered computed properties of the store and are suitable for derived state:
getters: {
// Basic getter
totalPrice: state => {
return state.products.reduce((sum, product) => sum + product.price, 0)
},
// Getter returning a function
getProductById: state => id => {
return state.products.find(product => product.id === id)
},
// Using other getters
discountedProducts: (state, getters) => {
return state.products.map(product => ({
...product,
discountPrice: product.price * 0.9
}))
}
}
Modular Organization
When the application grows, the store can be split into modules:
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
}
})
Strict Mode
Enable strict mode in development to prevent direct state modifications:
const store = new Vuex.Store({
strict: process.env.NODE_ENV !== 'production',
// ...other configurations
})
Plugin Development
Extend store functionality with plugins, such as a persistence plugin:
const persistPlugin = store => {
// Restore state from local storage on initialization
const savedState = localStorage.getItem('vuex-state')
if (savedState) {
store.replaceState(JSON.parse(savedState))
}
// Subscribe to mutation changes
store.subscribe((mutation, state) => {
localStorage.setItem('vuex-state', JSON.stringify(state))
})
}
const store = new Vuex.Store({
plugins: [persistPlugin],
// ...other configurations
})
Integration with Components
Use mapHelpers in components to simplify store access:
import { mapState, mapGetters, mapActions } from 'vuex'
export default {
computed: {
// Array syntax
...mapState(['user', 'products']),
// Object syntax
...mapState({
userName: state => state.user.name,
firstProduct: state => state.products[0]
}),
// Getters mapping
...mapGetters(['totalPrice', 'discountedProducts'])
},
methods: {
// Actions mapping
...mapActions(['fetchUser', 'initApp']),
// Namespaced actions
...mapActions('user', ['updateProfile'])
}
}
Form Handling
Handling two-way binding for forms in Vuex:
export default {
data() {
return {
localUser: {}
}
},
created() {
// Copy state to local data on initialization
this.localUser = { ...this.$store.state.user }
},
methods: {
updateUser() {
// Update state on submission
this.$store.commit('UPDATE_USER', this.localUser)
}
}
}
Testing Related
Writing testable store code:
// Export options separately for testing
export const storeOptions = {
state: { count: 0 },
mutations: {
increment(state) {
state.count++
}
},
actions: {
asyncIncrement({ commit }) {
setTimeout(() => {
commit('increment')
}, 100)
}
}
}
// Test example
describe('store', () => {
it('increment mutation', () => {
const state = { count: 0 }
storeOptions.mutations.increment(state)
expect(state.count).toBe(1)
})
})
Type Hints
Adding TypeScript support for Options-style Store:
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
}
}
})
Performance Optimization
Techniques for optimizing Options-style Store in large applications:
const store = new Vuex.Store({
// Use a function to return the state object to avoid shared references between modules
state: () => ({
largeData: null
}),
// Lazy registration of dynamic modules
modules: {
bigModule: {
namespaced: true,
// Dynamically import module definition
...import('./big-module')
}
}
})
Common Patterns
Common design patterns in Options-style Store:
const store = new Vuex.Store({
// State grouping
state: {
ui: {
loading: false,
theme: 'light'
},
data: {
users: [],
products: []
}
},
// Factory function to create modules
modules: {
dynamicModule: createDynamicModule()
}
})
function createDynamicModule() {
return {
state: () => ({ value: 0 }),
mutations: {
increment(state) {
state.value++
}
}
}
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:组合式Store写法
下一篇:Store间相互调用