@dxtmisha/wiki 0.24.0 → 0.24.1
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 +1 -1
- 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,312 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/functional/en/Composables/useTranslateRef'/>
|
|
4
|
+
|
|
5
|
+
# Composable useTranslateRef
|
|
6
|
+
|
|
7
|
+
Composable for getting translated texts by array of keys or string with key. Provides reactive variable that automatically updates when application language changes. Supports dynamic loading of translations from server and text templating with value substitution.
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
- **Reactive translations** — automatic updates when language changes
|
|
12
|
+
- **Batch loading** — fetch multiple translations at once
|
|
13
|
+
- **Dynamic loading** — automatic loading of missing translations from server
|
|
14
|
+
- **Templating** — value substitution in translation text
|
|
15
|
+
- **Synchronous fallback** — instant return of key before translation loads
|
|
16
|
+
- **Type safety** — full TypeScript support with automatic type inference
|
|
17
|
+
- **Request optimization** — request batching to server (160ms timeout)
|
|
18
|
+
- **Geo integration** — automatic language detection from geolocation
|
|
19
|
+
|
|
20
|
+
## Function
|
|
21
|
+
|
|
22
|
+
### `useTranslateRef`
|
|
23
|
+
|
|
24
|
+
Creates reactive variable with translations by array of keys.
|
|
25
|
+
|
|
26
|
+
**Parameters:**
|
|
27
|
+
- `names: (string | string[])[]` — array of translation keys or arrays with key and template parameters
|
|
28
|
+
|
|
29
|
+
**Returns:** `ShallowRef<TranslateList<T>>` — reactive object with translations
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
import { useTranslateRef } from '@dxtmisha/functional'
|
|
33
|
+
|
|
34
|
+
// Simple translation
|
|
35
|
+
const texts = useTranslateRef(['hello', 'goodbye', 'welcome'])
|
|
36
|
+
console.log(texts.value.hello) // 'Hello'
|
|
37
|
+
console.log(texts.value.goodbye) // 'Goodbye'
|
|
38
|
+
|
|
39
|
+
// With templating
|
|
40
|
+
const messages = useTranslateRef([
|
|
41
|
+
['greeting', 'John'],
|
|
42
|
+
['count', '5']
|
|
43
|
+
])
|
|
44
|
+
console.log(messages.value.greeting) // 'Hello, John!'
|
|
45
|
+
console.log(messages.value.count) // 'Found: 5 items'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### `t` (alias)
|
|
49
|
+
|
|
50
|
+
Short alias for `useTranslateRef`.
|
|
51
|
+
|
|
52
|
+
**Parameters:**
|
|
53
|
+
- `names: string[]` — array of translation keys
|
|
54
|
+
|
|
55
|
+
**Returns:** `ShallowRef<TranslateList<T>>` — reactive object with translations
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
import { t } from '@dxtmisha/functional'
|
|
59
|
+
|
|
60
|
+
// Short notation
|
|
61
|
+
const texts = t(['save', 'cancel', 'delete'])
|
|
62
|
+
console.log(texts.value.save) // 'Save'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Basic Usage
|
|
66
|
+
|
|
67
|
+
### Basic Translation
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
import { useTranslateRef } from '@dxtmisha/functional'
|
|
71
|
+
|
|
72
|
+
// Get multiple translations
|
|
73
|
+
const translations = useTranslateRef([
|
|
74
|
+
'button.save',
|
|
75
|
+
'button.cancel',
|
|
76
|
+
'message.success'
|
|
77
|
+
])
|
|
78
|
+
|
|
79
|
+
// Access translations
|
|
80
|
+
console.log(translations.value['button.save']) // 'Save'
|
|
81
|
+
console.log(translations.value['button.cancel']) // 'Cancel'
|
|
82
|
+
console.log(translations.value['message.success']) // 'Success!'
|
|
83
|
+
|
|
84
|
+
// Automatic update on language change
|
|
85
|
+
// Geo.setLocation('ru-RU')
|
|
86
|
+
// translations.value['button.save'] === 'Сохранить'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Using `t` alias
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
import { t } from '@dxtmisha/functional'
|
|
93
|
+
|
|
94
|
+
// Short notation for translations
|
|
95
|
+
const texts = t(['home', 'about', 'contact'])
|
|
96
|
+
|
|
97
|
+
console.log(texts.value.home) // 'Home'
|
|
98
|
+
console.log(texts.value.about) // 'About'
|
|
99
|
+
console.log(texts.value.contact) // 'Contact'
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Usage in Components
|
|
103
|
+
|
|
104
|
+
### Basic Form
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
import { useTranslateRef } from '@dxtmisha/functional'
|
|
108
|
+
|
|
109
|
+
export default {
|
|
110
|
+
setup() {
|
|
111
|
+
const t = useTranslateRef([
|
|
112
|
+
'form.name',
|
|
113
|
+
'form.email',
|
|
114
|
+
'form.submit',
|
|
115
|
+
'form.reset'
|
|
116
|
+
])
|
|
117
|
+
|
|
118
|
+
return { t }
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Template:
|
|
123
|
+
// <form>
|
|
124
|
+
// <input :placeholder="t['form.name']" />
|
|
125
|
+
// <input :placeholder="t['form.email']" />
|
|
126
|
+
// <button>{{ t['form.submit'] }}</button>
|
|
127
|
+
// <button type="reset">{{ t['form.reset'] }}</button>
|
|
128
|
+
// </form>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Navigation Menu
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
import { t } from '@dxtmisha/functional'
|
|
135
|
+
|
|
136
|
+
export default {
|
|
137
|
+
setup() {
|
|
138
|
+
const menu = t([
|
|
139
|
+
'menu.home',
|
|
140
|
+
'menu.products',
|
|
141
|
+
'menu.services',
|
|
142
|
+
'menu.contact'
|
|
143
|
+
])
|
|
144
|
+
|
|
145
|
+
return { menu }
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Template:
|
|
150
|
+
// <nav>
|
|
151
|
+
// <a href="/">{{ menu['menu.home'] }}</a>
|
|
152
|
+
// <a href="/products">{{ menu['menu.products'] }}</a>
|
|
153
|
+
// <a href="/services">{{ menu['menu.services'] }}</a>
|
|
154
|
+
// <a href="/contact">{{ menu['menu.contact'] }}</a>
|
|
155
|
+
// </nav>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Text Templating
|
|
159
|
+
|
|
160
|
+
### Value Substitution
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
import { useTranslateRef } from '@dxtmisha/functional'
|
|
164
|
+
|
|
165
|
+
// Translations with parameters
|
|
166
|
+
// Translation file: { "greeting": "Hello, {0}!", "items": "Found {0} of {1}" }
|
|
167
|
+
const messages = useTranslateRef([
|
|
168
|
+
['greeting', 'John'],
|
|
169
|
+
['items', '5', '10']
|
|
170
|
+
])
|
|
171
|
+
|
|
172
|
+
console.log(messages.value.greeting) // 'Hello, John!'
|
|
173
|
+
console.log(messages.value.items) // 'Found 5 of 10'
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Dynamic Parameters
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
import { ref, computed } from 'vue'
|
|
180
|
+
import { useTranslateRef } from '@dxtmisha/functional'
|
|
181
|
+
|
|
182
|
+
export default {
|
|
183
|
+
setup() {
|
|
184
|
+
const userName = ref('John')
|
|
185
|
+
const count = ref(5)
|
|
186
|
+
|
|
187
|
+
// Base translations
|
|
188
|
+
const t = useTranslateRef(['welcome', 'total'])
|
|
189
|
+
|
|
190
|
+
// Dynamic substitution in template
|
|
191
|
+
const welcomeMessage = computed(() =>
|
|
192
|
+
t.value.welcome.replace('{0}', userName.value)
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
const totalMessage = computed(() =>
|
|
196
|
+
t.value.total.replace('{0}', count.value)
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
return { welcomeMessage, totalMessage }
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Automatic Update on Language Change
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
import { watch } from 'vue'
|
|
208
|
+
import { useTranslateRef } from '@dxtmisha/functional'
|
|
209
|
+
import { Geo } from '@dxtmisha/functional'
|
|
210
|
+
|
|
211
|
+
// Translations automatically update on language change
|
|
212
|
+
const texts = useTranslateRef(['title', 'description'])
|
|
213
|
+
|
|
214
|
+
console.log(texts.value.title) // 'Title' (en-US)
|
|
215
|
+
|
|
216
|
+
// Change language
|
|
217
|
+
Geo.setLocation('ru-RU')
|
|
218
|
+
|
|
219
|
+
// texts.value automatically updates
|
|
220
|
+
// texts.value.title === 'Заголовок'
|
|
221
|
+
|
|
222
|
+
// Can track changes
|
|
223
|
+
watch(() => texts.value, (newTranslations) => {
|
|
224
|
+
console.log('Translations updated:', newTranslations)
|
|
225
|
+
})
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Integration with Translate Class
|
|
229
|
+
|
|
230
|
+
Composable uses `Translate` class for translation management:
|
|
231
|
+
|
|
232
|
+
```javascript
|
|
233
|
+
import { Translate } from '@dxtmisha/functional'
|
|
234
|
+
|
|
235
|
+
// Set URL for loading translations
|
|
236
|
+
Translate.setUrl('/api/translations')
|
|
237
|
+
|
|
238
|
+
// Set request parameter name
|
|
239
|
+
Translate.setPropsName('keys')
|
|
240
|
+
|
|
241
|
+
// Add translations manually (for SSR or tests)
|
|
242
|
+
Translate.addSync({
|
|
243
|
+
'button.save': 'Save',
|
|
244
|
+
'button.cancel': 'Cancel'
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
// Get single translation
|
|
248
|
+
const text = await Translate.get('button.save')
|
|
249
|
+
console.log(text) // 'Save'
|
|
250
|
+
|
|
251
|
+
// Synchronous get
|
|
252
|
+
const syncText = Translate.getSync('button.save')
|
|
253
|
+
console.log(syncText) // 'Save'
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Usage Examples
|
|
257
|
+
|
|
258
|
+
### Data Table
|
|
259
|
+
|
|
260
|
+
```javascript
|
|
261
|
+
const table = useTranslateRef([
|
|
262
|
+
'table.name',
|
|
263
|
+
'table.email',
|
|
264
|
+
'table.status',
|
|
265
|
+
'table.actions'
|
|
266
|
+
])
|
|
267
|
+
|
|
268
|
+
// In template:
|
|
269
|
+
// <thead>
|
|
270
|
+
// <th>{{ table['table.name'] }}</th>
|
|
271
|
+
// <th>{{ table['table.email'] }}</th>
|
|
272
|
+
// <th>{{ table['table.status'] }}</th>
|
|
273
|
+
// <th>{{ table['table.actions'] }}</th>
|
|
274
|
+
// </thead>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Validation Messages
|
|
278
|
+
|
|
279
|
+
```javascript
|
|
280
|
+
const validation = useTranslateRef([
|
|
281
|
+
'validation.required',
|
|
282
|
+
'validation.email',
|
|
283
|
+
'validation.minLength',
|
|
284
|
+
'validation.maxLength'
|
|
285
|
+
])
|
|
286
|
+
|
|
287
|
+
const validateField = (value) => {
|
|
288
|
+
if (!value) return validation.value['validation.required']
|
|
289
|
+
if (value.length < 3) return validation.value['validation.minLength']
|
|
290
|
+
return null
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Dynamic Content
|
|
295
|
+
|
|
296
|
+
```javascript
|
|
297
|
+
import { computed } from 'vue'
|
|
298
|
+
|
|
299
|
+
const status = ref('pending')
|
|
300
|
+
const messages = useTranslateRef([
|
|
301
|
+
'status.pending',
|
|
302
|
+
'status.approved',
|
|
303
|
+
'status.rejected'
|
|
304
|
+
])
|
|
305
|
+
|
|
306
|
+
const statusText = computed(() =>
|
|
307
|
+
messages.value[`status.${status.value}`]
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
console.log(statusText.value) // 'Pending' (when status = 'pending')
|
|
311
|
+
```
|
|
312
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {Meta} from '@storybook/addon-docs/blocks'
|
|
2
|
+
|
|
3
|
+
<Meta title='@dxtmisha/functional/ru/About'/>
|
|
4
|
+
|
|
5
|
+
# @dxtmisha/functional
|
|
6
|
+
|
|
7
|
+
Библиотека функциональных утилит для экосистемы DXT UI. Содержит готовые решения для типовых задач веб-разработки: работа с HTTP-запросами, геолокация, работа с датами, кеширование данных и многое другое.
|
|
8
|
+
|
|
9
|
+
## Что входит в пакет
|
|
10
|
+
|
|
11
|
+
### Классы (20+)
|
|
12
|
+
|
|
13
|
+
- **Api** — выполнение HTTP-запросов с поддержкой кеширования, загрузочных индикаторов и эмуляции ответов
|
|
14
|
+
- **Geo** — определение страны и языка пользователя, работа с геоданными и часовыми поясами
|
|
15
|
+
- **Datetime** — работа с датами: форматирование, манипуляции, сравнение с учётом локализации
|
|
16
|
+
- **Cache** — система кеширования данных с автоматической инвалидацией
|
|
17
|
+
- **GeoFlag** — доступ к флагам стран (200+) с локализованными названиями
|
|
18
|
+
- **GeoPhone** — телефонные коды и маски форматирования для всех стран
|
|
19
|
+
- **GeoIntl** — интернационализация: форматирование чисел, валют, дат по региональным стандартам
|
|
20
|
+
- **Cookie** — удобная работа с cookies
|
|
21
|
+
- **Hash** — управление параметрами в URL hash
|
|
22
|
+
- **DataStorage** — типизированная работа с localStorage и sessionStorage
|
|
23
|
+
- **Loading** — глобальное управление индикаторами загрузки
|
|
24
|
+
- **Translate** — система переводов с поддержкой подстановок
|
|
25
|
+
- **Icons** — управление иконками и SVG-спрайтами
|
|
26
|
+
|
|
27
|
+
### Композаблы для Vue 3 (10+)
|
|
28
|
+
|
|
29
|
+
Реактивные обёртки над классами для использования в Vue-компонентах:
|
|
30
|
+
|
|
31
|
+
- **useApiRef** — реактивные HTTP-запросы с автоматическим управлением состоянием загрузки
|
|
32
|
+
- **useGeoIntlRef** — реактивное форматирование с учётом локали пользователя
|
|
33
|
+
- **useStorageRef** — двусторонняя синхронизация ref с localStorage/sessionStorage
|
|
34
|
+
- **useHashRef** — двусторонняя синхронизация ref с URL hash
|
|
35
|
+
- **useCookieRef** — реактивная работа с cookies
|
|
36
|
+
- **useLoadingRef** — реактивное отслеживание состояния загрузки
|
|
37
|
+
- **useTranslateRef** — реактивная система переводов
|
|
38
|
+
|
|
39
|
+
### Функции-помощники (100+)
|
|
40
|
+
|
|
41
|
+
**Работа с массивами:** преобразование в массив, фильтрация, итерация, заполнение, уникальные значения
|
|
42
|
+
|
|
43
|
+
**Работа с объектами:** глубокое копирование, слияние объектов, получение значений по пути, сравнение
|
|
44
|
+
|
|
45
|
+
**Работа со строками:** преобразование регистра (camelCase, kebabCase), заполнение строк, применение шаблонов
|
|
46
|
+
|
|
47
|
+
**Валидация:** проверка типов данных, проверка на заполненность, сравнение значений
|
|
48
|
+
|
|
49
|
+
**DOM-утилиты:** поиск элементов, создание элементов, работа с атрибутами, прокрутка
|
|
50
|
+
|
|
51
|
+
**Математика:** безопасное преобразование в числа, проценты, случайные числа, пошаговые значения
|
|
52
|
+
|
|
53
|
+
**Асинхронность:** безопасное выполнение промисов и функций, работа с фреймами анимации
|
|
54
|
+
|
|
55
|
+
**Буфер обмена:** копирование и чтение данных из буфера
|
|
@@ -13,7 +13,7 @@ import {Meta} from '@storybook/addon-docs/blocks'
|
|
|
13
13
|
- **Автоматическая сериализация** — JSON сериализация/десериализация обрабатывается автоматически
|
|
14
14
|
- **Валидация времени кеша** — опциональное истечение кеша с автоматической очисткой
|
|
15
15
|
- **Singleton паттерн** — переиспользует экземпляры для одинаковых ключей хранения
|
|
16
|
-
- **Управление префиксами** — настраиваемый префикс для всех ключей хранения
|
|
16
|
+
- **Управление префиксами** — настраиваемый префикс для всех ключей хранения (по умолчанию 'ui-storage')
|
|
17
17
|
- **Поддержка функций как значений** — принимает функции как значения для динамической генерации данных
|
|
18
18
|
- **Совместимость с браузерами** — безопасное использование с серверным рендерингом
|
|
19
19
|
|
|
@@ -26,6 +26,8 @@ import {Meta} from '@storybook/addon-docs/blocks'
|
|
|
26
26
|
**Параметры:**
|
|
27
27
|
- `newPrefix: string` — новый префикс для ключей хранения
|
|
28
28
|
|
|
29
|
+
**Возвращает:** `void`
|
|
30
|
+
|
|
29
31
|
```javascript
|
|
30
32
|
import { DataStorage } from '@dxtmisha/functional'
|
|
31
33
|
|
|
@@ -33,7 +35,8 @@ import { DataStorage } from '@dxtmisha/functional'
|
|
|
33
35
|
DataStorage.setPrefix('myapp-storage')
|
|
34
36
|
|
|
35
37
|
// Все ключи хранения теперь будут использовать этот префикс:
|
|
36
|
-
// 'user-settings' → 'myapp-
|
|
38
|
+
// 'user-settings' → 'myapp-storage__user-settings'
|
|
39
|
+
// По умолчанию префикс: 'ui-storage'
|
|
37
40
|
```
|
|
38
41
|
|
|
39
42
|
## Конструктор
|
|
@@ -46,6 +49,8 @@ DataStorage.setPrefix('myapp-storage')
|
|
|
46
49
|
- `name: string` — имя ключа хранения
|
|
47
50
|
- `isSession?: boolean` — использовать sessionStorage вместо localStorage (по умолчанию: false)
|
|
48
51
|
|
|
52
|
+
**Возвращает:** `DataStorage<T>` — экземпляр класса (или существующий из кеша)
|
|
53
|
+
|
|
49
54
|
```javascript
|
|
50
55
|
// Экземпляр localStorage
|
|
51
56
|
const userPrefs = new DataStorage('user-preferences')
|
|
@@ -66,7 +71,7 @@ console.log(userPrefs === sameInstance) // true
|
|
|
66
71
|
|
|
67
72
|
**Параметры:**
|
|
68
73
|
- `defaultValue?: T | (() => T)` — значение по умолчанию или функция, если данные не найдены (опционально)
|
|
69
|
-
- `cache?: number` — время кеширования в
|
|
74
|
+
- `cache?: number` — время кеширования в **секундах** для валидации (опционально)
|
|
70
75
|
|
|
71
76
|
**Возвращает:** `T | undefined` — сохранённые данные, значение по умолчанию или undefined
|
|
72
77
|
|
|
@@ -88,8 +93,10 @@ const config = settings.get(() => ({
|
|
|
88
93
|
created: Date.now()
|
|
89
94
|
}))
|
|
90
95
|
|
|
91
|
-
// Получить с валидацией кеша (10 минут)
|
|
92
|
-
const cachedData = settings.get(null, 600)
|
|
96
|
+
// Получить с валидацией кеша (600 секунд = 10 минут)
|
|
97
|
+
const cachedData = settings.get(null, 600)
|
|
98
|
+
// Возвращает undefined если данные старше 10 минут
|
|
99
|
+
// Если кеш валиден - возвращает сохранённые данные
|
|
93
100
|
```
|
|
94
101
|
|
|
95
102
|
### `set`
|
|
@@ -131,108 +138,79 @@ const userStorage = new DataStorage('user-data')
|
|
|
131
138
|
userStorage.set({ name: 'Иван', preferences: { theme: 'dark' } })
|
|
132
139
|
console.log(userStorage.get()) // { name: 'Иван', preferences: { theme: 'dark' } }
|
|
133
140
|
|
|
134
|
-
//
|
|
141
|
+
// Удаление
|
|
135
142
|
userStorage.remove()
|
|
136
143
|
console.log(userStorage.get()) // undefined
|
|
137
144
|
|
|
138
|
-
// Цепочка вызовов
|
|
139
|
-
|
|
140
|
-
|
|
145
|
+
// Цепочка вызовов
|
|
146
|
+
userStorage
|
|
147
|
+
.set({ temp: 'data' })
|
|
148
|
+
.remove() // Удаляет только что сохранённые данные
|
|
149
|
+
```
|
|
141
150
|
|
|
142
|
-
|
|
143
|
-
tempStorage.set({ temp: true })
|
|
144
|
-
anotherStorage.set({ another: true })
|
|
151
|
+
### `update`
|
|
145
152
|
|
|
146
|
-
|
|
147
|
-
anotherStorage.remove() // Удалить другие данные
|
|
153
|
+
Обновляет данные из хранилища, перечитывая их заново.
|
|
148
154
|
|
|
149
|
-
|
|
150
|
-
console.log(anotherStorage.get()) // undefined
|
|
151
|
-
```
|
|
155
|
+
**Возвращает:** `this` — экземпляр DataStorage для цепочки вызовов
|
|
152
156
|
|
|
153
|
-
|
|
157
|
+
```javascript
|
|
158
|
+
const storage = new DataStorage('shared-data')
|
|
154
159
|
|
|
155
|
-
|
|
160
|
+
// Установить данные
|
|
161
|
+
storage.set({ value: 'initial' })
|
|
162
|
+
console.log(storage.get()) // { value: 'initial' }
|
|
156
163
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
constructor() {
|
|
160
|
-
this.storage = new DataStorage('user-settings')
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
getTheme() {
|
|
164
|
-
return this.storage.get('theme', 'light')
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
setTheme(theme) {
|
|
168
|
-
this.storage.set('theme', theme)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
getLanguage() {
|
|
172
|
-
return this.storage.get('language', 'ru')
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
setLanguage(language) {
|
|
176
|
-
this.storage.set('language', language)
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
exportSettings() {
|
|
180
|
-
return {
|
|
181
|
-
theme: this.getTheme(),
|
|
182
|
-
language: this.getLanguage(),
|
|
183
|
-
notifications: this.storage.get('notifications', true)
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
164
|
+
// Данные изменились в другой вкладке/окне браузера
|
|
165
|
+
// или напрямую через localStorage.setItem()
|
|
187
166
|
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
167
|
+
// Обновить данные из хранилища
|
|
168
|
+
storage.update()
|
|
169
|
+
console.log(storage.get()) // Получит актуальные данные из хранилища
|
|
170
|
+
|
|
171
|
+
// Цепочка вызовов
|
|
172
|
+
storage.update().get() // Обновить и получить свежие данные
|
|
192
173
|
```
|
|
193
174
|
|
|
194
|
-
|
|
175
|
+
## Практические примеры
|
|
176
|
+
|
|
177
|
+
### Настройки пользователя
|
|
195
178
|
|
|
196
179
|
```javascript
|
|
197
|
-
const
|
|
180
|
+
const settings = new DataStorage('user-settings')
|
|
198
181
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
182
|
+
// Получить с значением по умолчанию
|
|
183
|
+
const theme = settings.get(() => 'light')
|
|
184
|
+
console.log(theme) // 'light' или сохранённое значение
|
|
203
185
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
return appCache.get(key)
|
|
207
|
-
}
|
|
186
|
+
// Сохранить новое значение
|
|
187
|
+
settings.set('dark')
|
|
208
188
|
|
|
209
|
-
//
|
|
210
|
-
|
|
211
|
-
const cached = getCachedData('/users')
|
|
212
|
-
console.log('Кешированные данные:', cached)
|
|
189
|
+
// Удалить настройки
|
|
190
|
+
settings.remove()
|
|
213
191
|
```
|
|
214
192
|
|
|
215
|
-
###
|
|
193
|
+
### Кеш данных с TTL
|
|
216
194
|
|
|
217
195
|
```javascript
|
|
218
|
-
|
|
196
|
+
async function fetchWithCache(url, cacheDuration = 300) {
|
|
197
|
+
const storage = new DataStorage(`api_${url}`)
|
|
219
198
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
199
|
+
// Попытка получить из кеша (cacheDuration в секундах)
|
|
200
|
+
const cached = storage.get(undefined, cacheDuration)
|
|
201
|
+
if (cached) return cached
|
|
223
202
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
203
|
+
// Загрузка свежих данных
|
|
204
|
+
const response = await fetch(url)
|
|
205
|
+
const data = await response.json()
|
|
227
206
|
|
|
228
|
-
|
|
229
|
-
|
|
207
|
+
// Сохранение в кеш
|
|
208
|
+
storage.set(data)
|
|
209
|
+
return data
|
|
230
210
|
}
|
|
231
211
|
|
|
232
212
|
// Использование
|
|
233
|
-
|
|
234
|
-
const draft = loadFormDraft()
|
|
235
|
-
console.log('Черновик формы:', draft)
|
|
213
|
+
const users = await fetchWithCache('/api/users', 600) // Кеш на 10 минут
|
|
236
214
|
```
|
|
237
215
|
|
|
238
|
-
Класс DataStorage предоставляет единый интерфейс для работы с браузерными хранилищами, обеспечивая типобезопасность, автоматическую сериализацию и гибкое управление
|
|
216
|
+
Класс DataStorage предоставляет единый интерфейс для работы с браузерными хранилищами, обеспечивая типобезопасность, автоматическую сериализацию и гибкое управление временем жизни данных с поддержкой singleton паттерна для эффективного использования памяти.
|