@dxtmisha/wiki 0.24.0 → 0.24.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/src/media/functional/en/about.mdx +55 -0
- package/src/media/functional/en/dataStorage.mdx +61 -83
- package/src/media/functional/en/useApiRef.mdx +517 -0
- package/src/media/functional/en/useBroadcastValueRef.mdx +344 -0
- package/src/media/functional/en/useCookieRef.mdx +348 -0
- package/src/media/functional/en/useGeoIntlRef.mdx +288 -0
- package/src/media/functional/en/useHashRef.mdx +302 -0
- package/src/media/functional/en/useLazyRef.mdx +329 -0
- package/src/media/functional/en/useLoadingRef.mdx +159 -0
- package/src/media/functional/en/useSessionRef.mdx +248 -0
- package/src/media/functional/en/useStorageRef.mdx +242 -0
- package/src/media/functional/en/useTranslateRef.mdx +312 -0
- package/src/media/functional/ru/about.mdx +55 -0
- package/src/media/functional/ru/dataStorage.mdx +59 -81
- package/src/media/functional/ru/useApiRef.mdx +517 -0
- package/src/media/functional/ru/useBroadcastValueRef.mdx +344 -0
- package/src/media/functional/ru/useCookieRef.mdx +348 -0
- package/src/media/functional/ru/useGeoIntlRef.mdx +288 -0
- package/src/media/functional/ru/useHashRef.mdx +302 -0
- package/src/media/functional/ru/useLazyRef.mdx +329 -0
- package/src/media/functional/ru/useLoadingRef.mdx +159 -0
- package/src/media/functional/ru/useSessionRef.mdx +248 -0
- package/src/media/functional/ru/useStorageRef.mdx +242 -0
- package/src/media/functional/ru/useTranslateRef.mdx +312 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/functional/ru/Composables/useSessionRef'/>
|
|
4
|
+
|
|
5
|
+
# Композабл useSessionRef
|
|
6
|
+
|
|
7
|
+
Композабл для создания реактивной переменной, синхронизированной с sessionStorage. Автоматически управляет чтением и записью значений в хранилище сессии браузера с singleton паттерном. Данные сохраняются только в рамках текущей вкладки/окна браузера и удаляются при его закрытии.
|
|
8
|
+
|
|
9
|
+
## Основные возможности
|
|
10
|
+
|
|
11
|
+
- **Двусторонняя синхронизация** — автоматическая синхронизация между ref и sessionStorage
|
|
12
|
+
- **Автоматическое сохранение** — изменения ref автоматически сохраняются в sessionStorage
|
|
13
|
+
- **Изоляция по вкладкам** — данные не синхронизируются между вкладками (в отличие от localStorage)
|
|
14
|
+
- **Временное хранение** — данные удаляются при закрытии вкладки/браузера
|
|
15
|
+
- **Singleton паттерн** — переиспользование ref для одинаковых ключей
|
|
16
|
+
- **Типобезопасность** — полная поддержка TypeScript с дженериками
|
|
17
|
+
- **Значения по умолчанию** — поддержка начальных значений и функций-фабрик
|
|
18
|
+
- **Интеграция с DataStorage** — использует класс DataStorage для управления хранилищем
|
|
19
|
+
|
|
20
|
+
## Функция
|
|
21
|
+
|
|
22
|
+
### `useSessionRef`
|
|
23
|
+
|
|
24
|
+
Создаёт реактивную переменную, синхронизированную с sessionStorage.
|
|
25
|
+
|
|
26
|
+
**Параметры:**
|
|
27
|
+
- `name: string` — имя ключа в sessionStorage
|
|
28
|
+
- `defaultValue?: T | (() => T)` — значение по умолчанию или функция для его генерации (опционально)
|
|
29
|
+
|
|
30
|
+
**Возвращает:** `Ref<T | undefined>` — реактивная переменная Vue, связанная с sessionStorage
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
import { useSessionRef } from '@dxtmisha/functional'
|
|
34
|
+
|
|
35
|
+
// Простое использование
|
|
36
|
+
const wizardStep = useSessionRef('wizard-step')
|
|
37
|
+
|
|
38
|
+
// С значением по умолчанию
|
|
39
|
+
const currentStep = useSessionRef('current-step', 1)
|
|
40
|
+
|
|
41
|
+
// С функцией по умолчанию
|
|
42
|
+
const sessionId = useSessionRef('session-id', () => Math.random().toString(36))
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Основное использование
|
|
46
|
+
|
|
47
|
+
### Базовая синхронизация
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
import { useSessionRef } from '@dxtmisha/functional'
|
|
51
|
+
|
|
52
|
+
// Создание ref, синхронизированного с sessionStorage
|
|
53
|
+
const wizardProgress = useSessionRef('wizard-progress', { step: 1 })
|
|
54
|
+
|
|
55
|
+
// При изменении ref - sessionStorage автоматически обновляется
|
|
56
|
+
wizardProgress.value = { step: 2, data: { name: 'Иван' } }
|
|
57
|
+
|
|
58
|
+
// При перезагрузке страницы (в той же вкладке) значение восстанавливается
|
|
59
|
+
console.log(wizardProgress.value) // { step: 2, data: { name: 'Иван' } }
|
|
60
|
+
|
|
61
|
+
// При закрытии вкладки данные удаляются
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Singleton паттерн
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
// При повторном вызове с тем же именем возвращается существующий ref
|
|
68
|
+
const step1 = useSessionRef('wizard-step', 1)
|
|
69
|
+
const step2 = useSessionRef('wizard-step', 2)
|
|
70
|
+
|
|
71
|
+
console.log(step1 === step2) // true - тот же ref
|
|
72
|
+
|
|
73
|
+
step1.value = 3
|
|
74
|
+
console.log(step2.value) // 3 - оба указывают на один ref
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Использование в компонентах
|
|
78
|
+
|
|
79
|
+
### Многошаговый мастер
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
import { useSessionRef } from '@dxtmisha/functional'
|
|
83
|
+
|
|
84
|
+
export default {
|
|
85
|
+
setup() {
|
|
86
|
+
const currentStep = useSessionRef('wizard-step', 1)
|
|
87
|
+
const formData = useSessionRef('wizard-data', {
|
|
88
|
+
name: '',
|
|
89
|
+
email: '',
|
|
90
|
+
phone: ''
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const nextStep = () => {
|
|
94
|
+
currentStep.value++
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const prevStep = () => {
|
|
98
|
+
if (currentStep.value > 1) {
|
|
99
|
+
currentStep.value--
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
currentStep,
|
|
105
|
+
formData,
|
|
106
|
+
nextStep,
|
|
107
|
+
prevStep
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Template:
|
|
113
|
+
// <div>
|
|
114
|
+
// <div v-if="currentStep === 1">
|
|
115
|
+
// <input v-model="formData.name" placeholder="Имя" />
|
|
116
|
+
// </div>
|
|
117
|
+
// <div v-if="currentStep === 2">
|
|
118
|
+
// <input v-model="formData.email" placeholder="Email" />
|
|
119
|
+
// </div>
|
|
120
|
+
// <button @click="prevStep">Назад</button>
|
|
121
|
+
// <button @click="nextStep">Далее</button>
|
|
122
|
+
// </div>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Временное состояние фильтров
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
import { useSessionRef } from '@dxtmisha/functional'
|
|
129
|
+
|
|
130
|
+
export default {
|
|
131
|
+
setup() {
|
|
132
|
+
const filters = useSessionRef('search-filters', {
|
|
133
|
+
category: 'all',
|
|
134
|
+
priceMin: 0,
|
|
135
|
+
priceMax: 10000,
|
|
136
|
+
sortBy: 'name'
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
const resetFilters = () => {
|
|
140
|
+
filters.value = {
|
|
141
|
+
category: 'all',
|
|
142
|
+
priceMin: 0,
|
|
143
|
+
priceMax: 10000,
|
|
144
|
+
sortBy: 'name'
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return { filters, resetFilters }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Отличия от useStorageRef
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
// useStorageRef - данные сохраняются между сессиями браузера
|
|
157
|
+
const persistentTheme = useStorageRef('theme', 'light')
|
|
158
|
+
// Данные остаются даже после закрытия браузера
|
|
159
|
+
|
|
160
|
+
// useSessionRef - данные удаляются при закрытии вкладки
|
|
161
|
+
const temporaryFilters = useSessionRef('filters', {})
|
|
162
|
+
// Данные удаляются при закрытии вкладки/браузера
|
|
163
|
+
|
|
164
|
+
// useStorageRef синхронизируется между вкладками
|
|
165
|
+
// useSessionRef изолирован для каждой вкладки
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Работа с типами данных
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
// Числа
|
|
172
|
+
const step = useSessionRef<number>('step', 1)
|
|
173
|
+
step.value = 2
|
|
174
|
+
|
|
175
|
+
// Булевы значения
|
|
176
|
+
const isCompleted = useSessionRef<boolean>('completed', false)
|
|
177
|
+
isCompleted.value = true
|
|
178
|
+
|
|
179
|
+
// Объекты
|
|
180
|
+
const wizardData = useSessionRef('wizard-data', {
|
|
181
|
+
step: 1,
|
|
182
|
+
userData: {},
|
|
183
|
+
timestamp: Date.now()
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
// Массивы
|
|
187
|
+
const selectedItems = useSessionRef<number[]>('selected', [])
|
|
188
|
+
selectedItems.value.push(42)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Примеры использования
|
|
192
|
+
|
|
193
|
+
### Сохранение прогресса формы
|
|
194
|
+
|
|
195
|
+
```javascript
|
|
196
|
+
const registrationForm = useSessionRef('registration', {
|
|
197
|
+
step: 1,
|
|
198
|
+
personal: { name: '', email: '' },
|
|
199
|
+
address: { street: '', city: '' },
|
|
200
|
+
completed: false
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
// При заполнении данные сохраняются
|
|
204
|
+
registrationForm.value.personal.name = 'Иван'
|
|
205
|
+
registrationForm.value.step = 2
|
|
206
|
+
|
|
207
|
+
// При перезагрузке страницы (F5) данные восстанавливаются
|
|
208
|
+
// При закрытии вкладки - всё удаляется
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Временное состояние модального окна
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
const modalState = useSessionRef('modal', {
|
|
215
|
+
isOpen: false,
|
|
216
|
+
activeTab: 'details',
|
|
217
|
+
scrollPosition: 0
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
const openModal = () => {
|
|
221
|
+
modalState.value.isOpen = true
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const closeModal = () => {
|
|
225
|
+
modalState.value.isOpen = false
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Корзина покупок (временная)
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
const cart = useSessionRef<CartItem[]>('temp-cart', [])
|
|
233
|
+
|
|
234
|
+
const addToCart = (item: CartItem) => {
|
|
235
|
+
cart.value = [...cart.value, item]
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const removeFromCart = (itemId: number) => {
|
|
239
|
+
cart.value = cart.value.filter(item => item.id !== itemId)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const clearCart = () => {
|
|
243
|
+
cart.value = []
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// При закрытии вкладки корзина очищается автоматически
|
|
247
|
+
```
|
|
248
|
+
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/functional/ru/Composables/useStorageRef'/>
|
|
4
|
+
|
|
5
|
+
# Композабл useStorageRef
|
|
6
|
+
|
|
7
|
+
Композабл для создания реактивной переменной, синхронизированной с localStorage. Автоматически управляет чтением и записью значений в локальное хранилище браузера с поддержкой кеширования, синхронизации между вкладками и singleton паттерна для эффективного переиспользования.
|
|
8
|
+
|
|
9
|
+
## Основные возможности
|
|
10
|
+
|
|
11
|
+
- **Двусторонняя синхронизация** — автоматическая синхронизация между ref и localStorage
|
|
12
|
+
- **Автоматическое сохранение** — изменения ref автоматически сохраняются в localStorage
|
|
13
|
+
- **Кеширование с TTL** — опциональное время жизни кеша в секундах
|
|
14
|
+
- **Синхронизация между вкладками** — автоматическое обновление при изменениях в других вкладках
|
|
15
|
+
- **Singleton паттерн** — переиспользование ref для одинаковых ключей
|
|
16
|
+
- **Типобезопасность** — полная поддержка TypeScript с дженериками
|
|
17
|
+
- **Значения по умолчанию** — поддержка начальных значений и функций-фабрик
|
|
18
|
+
- **Интеграция с DataStorage** — использует класс DataStorage для управления хранилищем
|
|
19
|
+
|
|
20
|
+
## Функция
|
|
21
|
+
|
|
22
|
+
### `useStorageRef`
|
|
23
|
+
|
|
24
|
+
Создаёт реактивную переменную, синхронизированную с localStorage.
|
|
25
|
+
|
|
26
|
+
**Параметры:**
|
|
27
|
+
- `name: string` — имя ключа в localStorage
|
|
28
|
+
- `defaultValue?: T | (() => T)` — значение по умолчанию или функция для его генерации (опционально)
|
|
29
|
+
- `cache?: number` — время кеширования в секундах (опционально)
|
|
30
|
+
|
|
31
|
+
**Возвращает:** `Ref<T | undefined>` — реактивная переменная Vue, связанная с localStorage
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
import { useStorageRef } from '@dxtmisha/functional'
|
|
35
|
+
|
|
36
|
+
// Простое использование
|
|
37
|
+
const theme = useStorageRef('app-theme')
|
|
38
|
+
|
|
39
|
+
// С значением по умолчанию
|
|
40
|
+
const language = useStorageRef('app-language', 'ru')
|
|
41
|
+
|
|
42
|
+
// С функцией по умолчанию
|
|
43
|
+
const userId = useStorageRef('user-id', () => Math.random().toString(36))
|
|
44
|
+
|
|
45
|
+
// С кешированием (600 секунд = 10 минут)
|
|
46
|
+
const cachedData = useStorageRef('cached-data', null, 600)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Основное использование
|
|
50
|
+
|
|
51
|
+
### Базовая синхронизация
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
import { useStorageRef } from '@dxtmisha/functional'
|
|
55
|
+
|
|
56
|
+
// Создание ref, синхронизированного с localStorage
|
|
57
|
+
const userTheme = useStorageRef('theme', 'light')
|
|
58
|
+
|
|
59
|
+
// При изменении ref - localStorage автоматически обновляется
|
|
60
|
+
userTheme.value = 'dark'
|
|
61
|
+
// localStorage: { 'ui-storage__theme': '{"value":"dark","age":1234567890}' }
|
|
62
|
+
|
|
63
|
+
// При перезагрузке страницы значение восстанавливается
|
|
64
|
+
console.log(userTheme.value) // 'dark'
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Singleton паттерн
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
// При повторном вызове с тем же именем возвращается существующий ref
|
|
71
|
+
const theme1 = useStorageRef('app-theme', 'light')
|
|
72
|
+
const theme2 = useStorageRef('app-theme', 'dark')
|
|
73
|
+
|
|
74
|
+
console.log(theme1 === theme2) // true - тот же ref
|
|
75
|
+
|
|
76
|
+
theme1.value = 'blue'
|
|
77
|
+
console.log(theme2.value) // 'blue' - оба указывают на один ref
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Использование в компонентах
|
|
81
|
+
|
|
82
|
+
### Настройки пользователя
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
import { useStorageRef } from '@dxtmisha/functional'
|
|
86
|
+
|
|
87
|
+
export default {
|
|
88
|
+
setup() {
|
|
89
|
+
const theme = useStorageRef('user-theme', 'light')
|
|
90
|
+
const fontSize = useStorageRef('font-size', 16)
|
|
91
|
+
const notifications = useStorageRef('notifications', true)
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
theme,
|
|
95
|
+
fontSize,
|
|
96
|
+
notifications
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Template:
|
|
102
|
+
// <div>
|
|
103
|
+
// <select v-model="theme">
|
|
104
|
+
// <option value="light">Светлая</option>
|
|
105
|
+
// <option value="dark">Тёмная</option>
|
|
106
|
+
// </select>
|
|
107
|
+
// <input v-model.number="fontSize" type="number" />
|
|
108
|
+
// <input v-model="notifications" type="checkbox" />
|
|
109
|
+
// </div>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Кеширование данных API
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
import { useStorageRef } from '@dxtmisha/functional'
|
|
116
|
+
|
|
117
|
+
export default {
|
|
118
|
+
setup() {
|
|
119
|
+
// Кеш на 10 минут (600 секунд)
|
|
120
|
+
const userData = useStorageRef('user-data', null, 600)
|
|
121
|
+
|
|
122
|
+
const loadUserData = async () => {
|
|
123
|
+
if (userData.value) {
|
|
124
|
+
console.log('Данные из кеша')
|
|
125
|
+
return userData.value
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.log('Загрузка с сервера')
|
|
129
|
+
const response = await fetch('/api/user')
|
|
130
|
+
userData.value = await response.json()
|
|
131
|
+
return userData.value
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return { userData, loadUserData }
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Синхронизация между вкладками
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
import { useStorageRef } from '@dxtmisha/functional'
|
|
143
|
+
|
|
144
|
+
// В первой вкладке
|
|
145
|
+
const counter = useStorageRef('counter', 0)
|
|
146
|
+
counter.value = 5
|
|
147
|
+
|
|
148
|
+
// Во второй вкладке автоматически обновится
|
|
149
|
+
// counter.value === 5 (благодаря storage event)
|
|
150
|
+
|
|
151
|
+
// В третьей вкладке
|
|
152
|
+
const sameCounter = useStorageRef('counter', 0)
|
|
153
|
+
console.log(sameCounter.value) // 5
|
|
154
|
+
|
|
155
|
+
// Изменение в любой вкладке обновит все остальные
|
|
156
|
+
sameCounter.value = 10
|
|
157
|
+
// Все открытые вкладки получат counter.value === 10
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Работа с типами данных
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
// Числа
|
|
164
|
+
const count = useStorageRef<number>('count', 0)
|
|
165
|
+
count.value = 42
|
|
166
|
+
|
|
167
|
+
// Булевы значения
|
|
168
|
+
const isActive = useStorageRef<boolean>('active', false)
|
|
169
|
+
isActive.value = true
|
|
170
|
+
|
|
171
|
+
// Объекты
|
|
172
|
+
const settings = useStorageRef('settings', {
|
|
173
|
+
theme: 'dark',
|
|
174
|
+
language: 'ru',
|
|
175
|
+
notifications: true
|
|
176
|
+
})
|
|
177
|
+
settings.value.theme = 'light'
|
|
178
|
+
|
|
179
|
+
// Массивы
|
|
180
|
+
const items = useStorageRef<string[]>('items', [])
|
|
181
|
+
items.value.push('новый элемент')
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Примеры использования
|
|
185
|
+
|
|
186
|
+
### Сохранение состояния формы
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
const formData = useStorageRef('contact-form', {
|
|
190
|
+
name: '',
|
|
191
|
+
email: '',
|
|
192
|
+
message: ''
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
// При заполнении формы данные автоматически сохраняются
|
|
196
|
+
formData.value.name = 'Иван'
|
|
197
|
+
formData.value.email = 'ivan@example.com'
|
|
198
|
+
|
|
199
|
+
// При перезагрузке страницы данные восстанавливаются
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Избранное пользователя
|
|
203
|
+
|
|
204
|
+
```javascript
|
|
205
|
+
const favorites = useStorageRef<number[]>('favorites', [])
|
|
206
|
+
|
|
207
|
+
const addToFavorites = (id: number) => {
|
|
208
|
+
if (!favorites.value.includes(id)) {
|
|
209
|
+
favorites.value = [...favorites.value, id]
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const removeFromFavorites = (id: number) => {
|
|
214
|
+
favorites.value = favorites.value.filter(fav => fav !== id)
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Кеш с автообновлением
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
// Кеш на 5 минут
|
|
222
|
+
const newsData = useStorageRef('news', null, 300)
|
|
223
|
+
|
|
224
|
+
const fetchNews = async () => {
|
|
225
|
+
// Если кеш валиден - возвращаем сохранённые данные
|
|
226
|
+
if (newsData.value) return newsData.value
|
|
227
|
+
|
|
228
|
+
// Иначе загружаем свежие данные
|
|
229
|
+
const response = await fetch('/api/news')
|
|
230
|
+
newsData.value = await response.json()
|
|
231
|
+
return newsData.value
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Первый вызов - загружает с сервера
|
|
235
|
+
await fetchNews()
|
|
236
|
+
|
|
237
|
+
// Последующие вызовы в течение 5 минут - используют кеш
|
|
238
|
+
await fetchNews() // Из кеша
|
|
239
|
+
|
|
240
|
+
// Через 5+ минут - снова загрузит с сервера
|
|
241
|
+
```
|
|
242
|
+
|