← Назад к вопросам
В чем разница между action и mutation?
2.0 Middle🔥 111 комментариев
#State Management
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между Action и Mutation в Vuex
Mutation и Action — это два способа изменения состояния в Vuex (state management для Vue.js). Часто начинающие разработчики путают их, но их различия критичны для правильной архитектуры.
Mutation: Синхронное изменение состояния
Mutation — это единственный способ синхронно изменить состояние в Vuex:
const mutations = {
SET_USER(state, user) {
state.user = user;
},
INCREMENT_COUNTER(state, amount) {
state.counter += amount;
},
ADD_TODO(state, todo) {
state.todos.push(todo);
}
};
Особенности:
- Синхронны — выполняются мгновенно
- Принимают состояние первым параметром — state
- Должны быть чистыми функциями — не делать асинхронные операции
- Трассируются Dev Tools — каждое изменение видно в Vue DevTools
Action: Асинхронные операции и бизнес-логика
Action — это способ выполнить асинхронный код и затем вызвать mutation:
const actions = {
async fetchUser({ commit }, userId) {
try {
const response = await fetch(`/api/users/${userId}`);
const user = await response.json();
// Вызываем mutation для обновления состояния
commit('SET_USER', user);
} catch (error) {
commit('SET_ERROR', error.message);
}
},
async createTodo({ commit }, todoData) {
try {
const response = await api.post('/todos', todoData);
commit('ADD_TODO', response.data);
} catch (error) {
commit('SET_ERROR', error);
}
}
};
Особенности:
- Асинхронны — могут выполнять API запросы, таймауты и т.д.
- Первый параметр context — объект с { state, commit, dispatch, rootState, rootGetters }
- Вызывают mutations — для изменения состояния
- Могут вызывать другие actions — dispatch('otherAction')
Главная разница: Синхронность
// ПЛОХО: асинхронный код в mutation
const mutations = {
fetchAndSetUser(state, userId) {
// Это НАРУШЕНИЕ!
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(user => state.user = user); // Dev Tools не увидит!
}
};
// ХОРОШО: асинхронный код в action
const actions = {
async fetchUser({ commit }, userId) {
const response = await fetch(`/api/users/${userId}`);
const user = await response.json();
commit('SET_USER', user); // Трассируется
}
};
Архитектурный паттерн
Определяется строгое разделение:
Компонент
|
v
dispatch(action) -> выполнить логику
|
v
commit(mutation) -> изменить состояние
|
v
Верифицируется в Dev Tools
// Компонент
export default {
methods: {
async loadUser() {
// Вызываем ACTION
await this.$store.dispatch('fetchUser', userId);
// Затем состояние обновляется
},
handleClick() {
// Для синхронных изменений можно прямо в mutation
this.$store.commit('INCREMENT_COUNTER', 5);
}
}
};
Практические примеры
Пример 1: Загрузка данных с сервера
const store = {
state: {
users: [],
loading: false,
error: null
},
mutations: {
SET_LOADING(state, value) {
state.loading = value;
},
SET_USERS(state, users) {
state.users = users;
},
SET_ERROR(state, error) {
state.error = error;
}
},
actions: {
async loadUsers({ commit }) {
commit('SET_LOADING', true);
commit('SET_ERROR', null);
try {
const response = await fetch('/api/users');
const users = await response.json();
commit('SET_USERS', users);
} catch (error) {
commit('SET_ERROR', error.message);
} finally {
commit('SET_LOADING', false);
}
}
}
};
Пример 2: Условная логика в action
actions: {
// Action вызывает разные mutations в зависимости от условий
async toggleTodo({ state, commit }, todoId) {
const todo = state.todos.find(t => t.id === todoId);
if (!todo) {
commit('SET_ERROR', 'Todo not found');
return;
}
try {
await api.put(`/todos/${todoId}`, { completed: !todo.completed });
commit('TOGGLE_TODO', todoId); // Вызываем mutation
} catch (error) {
commit('SET_ERROR', error.message);
}
}
}
Когда использовать что
Используй Mutation когда:
- Нужно синхронно изменить состояние
- Нет асинхронных операций
- Изменение простое и локальное
commit('SET_THEME', 'dark');
commit('SET_COUNTER', value);
commit('TOGGLE_MODAL', true);
Используй Action когда:
- Нужно выполнить асинхронную операцию (fetch, API)
- Требуется условная логика перед изменением состояния
- Нужно вызвать несколько mutations
- Требуется обработка ошибок
dispatch('fetchUserData', userId);
dispatch('submitForm', formData);
dispatch('syncWithServer');
Сравнение в таблице
| Аспект | Mutation | Action |
|---|---|---|
| Синхронность | Только синхронный | Может быть асинхронный |
| Параметры | state, payload | context (commit, dispatch, state) |
| API запросы | Запрещены | Разрешены |
| Вызов | commit | dispatch |
| Трассировка | Видна в Dev Tools | Видна в Dev Tools |
| Использование | Изменение состояния | Бизнес-логика |
Практический совет
Думай о разделении так:
- Mutation — WHAT (ЧТО изменилось)
- Action — HOW (КАК и КОГДА это изменилось)
// Action отвечает на вопрос "Как?" — делаем API запрос
actions: {
async saveUser({ commit }, userData) {
const savedUser = await api.post('/users', userData);
// Mutation отвечает на вопрос "Что?" — обновляем состояние
commit('SET_USER', savedUser);
}
}
Это чёткое разделение делает код предсказуемым, тестируемым и отлаживаемым.