Оптимистичные обновления (Optimistic Updates) — это подход к обновлению состояния интерфейса до того, как сервер подтвердит изменение данных. В контексте Naive UI этот подход позволяет пользователю видеть мгновенный отклик интерфейса, что значительно повышает ощущение отзывчивости приложения.
Naive UI, будучи библиотекой компонентов Vue 3, не предоставляет встроенного механизма для оптимистичных обновлений, однако интеграция с реактивным состоянием Vue и инструментами управления состоянием, такими как Vuex или Pinia, делает реализацию гибкой и предсказуемой.
Допустим, есть компонент n-button, который увеличивает
счетчик на сервере и одновременно отображает локальное обновление
значения:
<template>
<n-button @click="increment">
{{ count }}
</n-button>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
// Оптимистичное обновление
count.value += 1
// Отправка запроса на сервер
fetch('/api/increment', {
method: 'POST',
body: JSON.stringify({ delta: 1 }),
}).then(async (response) => {
if (!response.ok) {
// Откат в случае ошибки
count.value -= 1
console.error('Ошибка обновления на сервере')
}
})
}
</script>
Ключевые моменты:
count изменяется сразу, обеспечивая
мгновенный отклик.Naive UI предоставляет множество интерактивных компонентов, таких как
n-input, n-select, n-data-table,
где оптимистичные обновления особенно полезны для улучшения UX.
Пример с n-input для редактирования имени
пользователя:
<template>
<n-input
v-model="localName"
@blur="updateName"
placeholder="Введите имя"
/>
</template>
<script setup>
import { ref } from 'vue'
const localName = ref('Иван')
let originalName = localName.value
async function updateName() {
const tempName = localName.value
originalName = tempName // Оптимистично обновляем
try {
const response = await fetch('/api/user/name', {
method: 'POST',
body: JSON.stringify({ name: tempName }),
})
if (!response.ok) throw new Error('Ошибка сервера')
} catch (error) {
// Откат в случае ошибки
localName.value = originalName
console.error(error)
}
}
</script>
При работе с таблицами данных (n-data-table) или
списками (n-list), оптимистичные обновления требуют особого
внимания к идентификации элементов и управлению состоянием:
Использование уникальных ключей Каждая строка
должна иметь уникальный id, чтобы легко откатывать
изменения при ошибках.
Локальная копия данных Создание отдельного массива для оптимистичных изменений позволяет изолировать локальное состояние от данных сервера:
const tableData = ref([...serverData])
const pendingUpdates = ref({})
function updateRow(rowId, newData) {
const index = tableData.value.findIndex(row => row.id === rowId)
if (index === -1) return
const originalRow = { ...tableData.value[index] }
tableData.value[index] = { ...tableData.value[index], ...newData }
pendingUpdates.value[rowId] = originalRow
fetch(`/api/row/${rowId}`, {
method: 'PUT',
body: JSON.stringify(newData)
}).then(res => {
if (!res.ok) {
// Откат в случае ошибки
tableData.value[index] = pendingUpdates.value[rowId]
delete pendingUpdates.value[rowId]
} else {
delete pendingUpdates.value[rowId]
}
})
}
Оптимистичные обновления не должны оставлять пользователя в
неведении. Naive UI предоставляет компоненты уведомлений
n-notification и n-message, которые легко
интегрируются:
import { createDiscreteApi } from 'naive-ui'
const { message } = createDiscreteApi(['message'])
function handleError(errorText) {
message.error(errorText)
}
Использование уведомлений повышает доверие пользователя к интерфейсу, особенно когда изменения не были приняты сервером.
Оптимистичные обновления в связке с Naive UI делают интерфейс быстрым и отзывчивым, позволяя создавать современные приложения с предсказуемым и приятным пользовательским опытом.