@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.
@@ -0,0 +1,329 @@
1
+ import {Meta} from '@storybook/addon-docs/blocks'
2
+
3
+ <Meta title='@dxtmisha/functional/ru/Composables/useLazyRef'/>
4
+
5
+ # Композабл useLazyRef
6
+
7
+ Композабл для отслеживания появления элементов на экране с использованием Intersection Observer API. Обеспечивает эффективную ленивую загрузку и рендеринг компонентов только когда они становятся видимыми в области просмотра. Идеально подходит для оптимизации производительности при работе с длинными списками, изображениями и тяжёлыми компонентами.
8
+
9
+ ## Основные возможности
10
+
11
+ - **Отслеживание видимости** — автоматическое определение когда элемент появляется в области просмотра
12
+ - **Intersection Observer API** — использует нативный браузерный API для эффективного отслеживания
13
+ - **Автоматическая очистка** — удаление наблюдателей при размонтировании компонентов
14
+ - **Реактивный статус** — возвращает реактивную переменную с состоянием видимости
15
+ - **Настраиваемые границы** — поддержка rootMargin для предзагрузки контента
16
+ - **Множественные элементы** — управление отслеживанием нескольких элементов одновременно
17
+ - **Graceful degradation** — работает без IntersectionObserver в старых браузерах
18
+
19
+ ## Функция
20
+
21
+ ### `useLazyRef`
22
+
23
+ Создаёт экземпляр для отслеживания видимости элементов на экране.
24
+
25
+ **Параметры:** нет
26
+
27
+ **Возвращает:** объект с методами:
28
+ - `intersectionObserver: IntersectionObserver | undefined` — экземпляр наблюдателя
29
+ - `addLazyItem: (element: Ref<HTMLElement>) => ShallowRef<boolean>` — добавить элемент для отслеживания
30
+ - `removeLazyItem: (element?: HTMLElement) => void` — удалить элемент из отслеживания
31
+ - `disconnectLazy: () => void` — отключить все наблюдатели
32
+
33
+ ```javascript
34
+ import { useLazyRef } from '@dxtmisha/functional'
35
+
36
+ // Создание экземпляра
37
+ const lazy = useLazyRef()
38
+
39
+ // Доступ к методам
40
+ const isVisible = lazy.addLazyItem(elementRef)
41
+ lazy.removeLazyItem(element)
42
+ lazy.disconnectLazy()
43
+ ```
44
+
45
+ ## Основное использование
46
+
47
+ ### `addLazyItem`
48
+
49
+ Добавляет элемент для отслеживания его видимости на экране.
50
+
51
+ **Параметры:**
52
+ - `element: Ref<HTMLElement>` — реактивная ссылка на HTML элемент
53
+
54
+ **Возвращает:** `ShallowRef<boolean>` — реактивная переменная со статусом видимости
55
+
56
+ ```javascript
57
+ import { ref } from 'vue'
58
+ import { useLazyRef } from '@dxtmisha/functional'
59
+
60
+ const lazy = useLazyRef()
61
+ const imageRef = ref(null)
62
+
63
+ // Добавление элемента для отслеживания
64
+ const isVisible = lazy.addLazyItem(imageRef)
65
+
66
+ // isVisible.value === true когда элемент видим
67
+ // isVisible.value === false когда элемент невидим
68
+
69
+ // В старых браузерах без IntersectionObserver
70
+ // isVisible.value === true сразу (fallback)
71
+ ```
72
+
73
+ ### `removeLazyItem`
74
+
75
+ Удаляет элемент из отслеживания и очищает ресурсы.
76
+
77
+ **Параметры:**
78
+ - `element?: HTMLElement` — HTML элемент для удаления
79
+
80
+ **Возвращает:** `void`
81
+
82
+ ```javascript
83
+ const element = document.getElementById('my-element')
84
+
85
+ // Удаление элемента из отслеживания
86
+ lazy.removeLazyItem(element)
87
+ ```
88
+
89
+ ### `disconnectLazy`
90
+
91
+ Отключает все наблюдатели и прекращает отслеживание всех элементов.
92
+
93
+ **Параметры:** нет
94
+
95
+ **Возвращает:** `void`
96
+
97
+ ```javascript
98
+ // Полная очистка при размонтировании
99
+ onBeforeUnmount(() => {
100
+ lazy.disconnectLazy()
101
+ })
102
+ ```
103
+
104
+ ## Использование в компонентах
105
+
106
+ ### Ленивая загрузка изображений
107
+
108
+ ```javascript
109
+ import { ref, watch } from 'vue'
110
+ import { useLazyRef } from '@dxtmisha/functional'
111
+
112
+ export default {
113
+ setup() {
114
+ const lazy = useLazyRef()
115
+ const imageRef = ref(null)
116
+ const imageLoaded = ref(false)
117
+
118
+ const isVisible = lazy.addLazyItem(imageRef)
119
+
120
+ watch(isVisible, (visible) => {
121
+ if (visible && !imageLoaded.value) {
122
+ imageLoaded.value = true
123
+ }
124
+ })
125
+
126
+ return { imageRef, imageLoaded }
127
+ }
128
+ }
129
+
130
+ // Template:
131
+ // <div ref="imageRef">
132
+ // <img v-if="imageLoaded" src="/path/to/image.jpg" />
133
+ // <div v-else class="placeholder">Загрузка...</div>
134
+ // </div>
135
+ ```
136
+
137
+ ### Бесконечная прокрутка
138
+
139
+ ```javascript
140
+ import { ref, watch } from 'vue'
141
+ import { useLazyRef } from '@dxtmisha/functional'
142
+
143
+ export default {
144
+ setup() {
145
+ const lazy = useLazyRef()
146
+ const items = ref([1, 2, 3, 4, 5])
147
+ const sentinelRef = ref(null)
148
+ const loading = ref(false)
149
+
150
+ const isSentinelVisible = lazy.addLazyItem(sentinelRef)
151
+
152
+ watch(isSentinelVisible, async (visible) => {
153
+ if (visible && !loading.value) {
154
+ loading.value = true
155
+ await new Promise(resolve => setTimeout(resolve, 1000))
156
+ items.value.push(items.value.length + 1)
157
+ loading.value = false
158
+ }
159
+ })
160
+
161
+ return { items, sentinelRef, loading }
162
+ }
163
+ }
164
+
165
+ // Template:
166
+ // <div>
167
+ // <div v-for="item in items" :key="item">Элемент {{ item }}</div>
168
+ // <div ref="sentinelRef" class="sentinel">
169
+ // <div v-if="loading">Загрузка...</div>
170
+ // </div>
171
+ // </div>
172
+ ```
173
+
174
+ ## Продвинутое использование
175
+
176
+ ### Отслеживание множества элементов
177
+
178
+ ```javascript
179
+ import { ref, onBeforeUnmount } from 'vue'
180
+ import { useLazyRef } from '@dxtmisha/functional'
181
+
182
+ export default {
183
+ setup() {
184
+ const lazy = useLazyRef()
185
+ const items = ref([
186
+ { id: 1, ref: ref(null), visible: null },
187
+ { id: 2, ref: ref(null), visible: null },
188
+ { id: 3, ref: ref(null), visible: null }
189
+ ])
190
+
191
+ // Добавление каждого элемента для отслеживания
192
+ items.value.forEach(item => {
193
+ item.visible = lazy.addLazyItem(item.ref)
194
+ })
195
+
196
+ onBeforeUnmount(() => {
197
+ lazy.disconnectLazy()
198
+ })
199
+
200
+ return { items }
201
+ }
202
+ }
203
+
204
+ // Template:
205
+ // <div v-for="item in items" :key="item.id">
206
+ // <div :ref="item.ref">
207
+ // <div v-if="item.visible.value">
208
+ // Контент элемента {{ item.id }}
209
+ // </div>
210
+ // <div v-else class="placeholder">...</div>
211
+ // </div>
212
+ // </div>
213
+ ```
214
+
215
+ ### Условное удаление элементов
216
+
217
+ ```javascript
218
+ import { ref, watch } from 'vue'
219
+ import { useLazyRef } from '@dxtmisha/functional'
220
+
221
+ export default {
222
+ setup() {
223
+ const lazy = useLazyRef()
224
+ const elementRef = ref(null)
225
+ const showElement = ref(true)
226
+
227
+ const isVisible = lazy.addLazyItem(elementRef)
228
+
229
+ // Удаление из отслеживания при скрытии
230
+ watch(showElement, (show) => {
231
+ if (!show && elementRef.value) {
232
+ lazy.removeLazyItem(elementRef.value)
233
+ }
234
+ })
235
+
236
+ return {
237
+ elementRef,
238
+ showElement,
239
+ isVisible
240
+ }
241
+ }
242
+ }
243
+ ```
244
+
245
+ ### Предзагрузка с rootMargin
246
+
247
+ ```javascript
248
+ // По умолчанию rootMargin: '128px 0px'
249
+ // Элементы начинают отслеживаться за 128px до входа в viewport
250
+
251
+ const lazy = useLazyRef()
252
+ const imageRef = ref(null)
253
+
254
+ // Изображение начнёт загружаться за 128px до видимости
255
+ const isVisible = lazy.addLazyItem(imageRef)
256
+
257
+ console.log('rootMargin обеспечивает плавную предзагрузку')
258
+ ```
259
+
260
+ ## Обработка отсутствия IntersectionObserver
261
+
262
+ ```javascript
263
+ import { useLazyRef } from '@dxtmisha/functional'
264
+
265
+ const lazy = useLazyRef()
266
+
267
+ // Проверка доступности API
268
+ if (lazy.intersectionObserver) {
269
+ console.log('IntersectionObserver доступен')
270
+ // Используем ленивую загрузку
271
+ } else {
272
+ console.log('IntersectionObserver не поддерживается')
273
+ // isVisible всегда будет true (fallback)
274
+ }
275
+
276
+ const elementRef = ref(null)
277
+ const isVisible = lazy.addLazyItem(elementRef)
278
+
279
+ // В старых браузерах isVisible.value === true сразу
280
+ // Контент загружается немедленно (graceful degradation)
281
+ ```
282
+
283
+ ## Оптимизация производительности
284
+
285
+ ### Ленивая загрузка в списках
286
+
287
+ ```javascript
288
+ import { ref } from 'vue'
289
+ import { useLazyRef } from '@dxtmisha/functional'
290
+
291
+ export default {
292
+ setup() {
293
+ const lazy = useLazyRef()
294
+ const products = ref([
295
+ { id: 1, name: 'Товар 1', image: '/img1.jpg' },
296
+ { id: 2, name: 'Товар 2', image: '/img2.jpg' },
297
+ // ... ещё 100 товаров
298
+ ])
299
+
300
+ // Создание refs для каждого товара
301
+ const productRefs = ref(products.value.map(() => ({
302
+ element: ref(null),
303
+ visible: null
304
+ })))
305
+
306
+ // Отслеживание видимости каждого товара
307
+ productRefs.value.forEach(item => {
308
+ item.visible = lazy.addLazyItem(item.element)
309
+ })
310
+
311
+ return {
312
+ products,
313
+ productRefs
314
+ }
315
+ }
316
+ }
317
+
318
+ // Template:
319
+ // <div v-for="(product, index) in products" :key="product.id">
320
+ // <div :ref="productRefs[index].element">
321
+ // <template v-if="productRefs[index].visible.value">
322
+ // <img :src="product.image" :alt="product.name" />
323
+ // <h3>{{ product.name }}</h3>
324
+ // </template>
325
+ // <div v-else class="product-skeleton">Загрузка...</div>
326
+ // </div>
327
+ // </div>
328
+ ```
329
+
@@ -0,0 +1,159 @@
1
+ import {Meta} from '@storybook/addon-docs/blocks'
2
+
3
+ <Meta title='@dxtmisha/functional/ru/Composables/useLoadingRef'/>
4
+
5
+ # Композабл useLoadingRef
6
+
7
+ Композабл для отслеживания глобального статуса загрузки приложения. Предоставляет реактивную переменную, которая автоматически обновляется при изменении состояния загрузки через класс Loading. Идеально подходит для отображения глобальных индикаторов загрузки, блокировки интерфейса во время асинхронных операций и координации множественных загрузочных процессов.
8
+
9
+ ## Основные возможности
10
+
11
+ - **Глобальный статус загрузки** — единое место для управления состоянием загрузки всего приложения
12
+ - **Реактивность** — автоматическое обновление при изменении статуса загрузки
13
+ - **Счётчик загрузок** — поддержка множественных одновременных операций загрузки
14
+ - **Автоматическая подписка** — композабл автоматически подписывается на события Loading
15
+ - **Типобезопасность** — полная поддержка TypeScript
16
+ - **Простая интеграция** — легко интегрируется с любыми компонентами Vue
17
+ - **Централизованное управление** — все компоненты используют один источник истины
18
+
19
+ ## Функция
20
+
21
+ ### `useLoadingRef`
22
+
23
+ Создаёт реактивную переменную, отслеживающую глобальный статус загрузки.
24
+
25
+ **Параметры:** нет
26
+
27
+ **Возвращает:** `ShallowRef<boolean>` — реактивная переменная со статусом загрузки
28
+
29
+ ```javascript
30
+ import { useLoadingRef } from '@dxtmisha/functional'
31
+
32
+ // Создание реактивной переменной
33
+ const isLoading = useLoadingRef()
34
+
35
+ // isLoading.value === true когда есть активные загрузки
36
+ // isLoading.value === false когда загрузок нет
37
+ ```
38
+
39
+ ## Основное использование
40
+
41
+ ### Базовое отслеживание загрузки
42
+
43
+ ```javascript
44
+ import { useLoadingRef } from '@dxtmisha/functional'
45
+ import { Loading } from '@dxtmisha/functional'
46
+
47
+ // В компоненте
48
+ const isLoading = useLoadingRef()
49
+
50
+ // Показать загрузчик
51
+ Loading.show()
52
+ console.log(isLoading.value) // true
53
+
54
+ // Скрыть загрузчик
55
+ Loading.hide()
56
+ console.log(isLoading.value) // false
57
+ ```
58
+
59
+ ### Работа с множественными загрузками
60
+
61
+ ```javascript
62
+ import { useLoadingRef, Loading } from '@dxtmisha/functional'
63
+
64
+ const isLoading = useLoadingRef()
65
+
66
+ // Первая операция загрузки
67
+ Loading.show()
68
+ console.log(isLoading.value) // true (счётчик = 1)
69
+
70
+ // Вторая операция загрузки
71
+ Loading.show()
72
+ console.log(isLoading.value) // true (счётчик = 2)
73
+
74
+ // Завершение первой операции
75
+ Loading.hide()
76
+ console.log(isLoading.value) // true (счётчик = 1)
77
+
78
+ // Завершение второй операции
79
+ Loading.hide()
80
+ console.log(isLoading.value) // false (счётчик = 0)
81
+ ```
82
+
83
+ ## Использование в компонентах
84
+
85
+ ### Глобальный индикатор загрузки
86
+
87
+ ```javascript
88
+ import { useLoadingRef } from '@dxtmisha/functional'
89
+
90
+ export default {
91
+ setup() {
92
+ const isLoading = useLoadingRef()
93
+
94
+ return { isLoading }
95
+ }
96
+ }
97
+
98
+ // Template:
99
+ // <div v-if="isLoading" class="global-loader">
100
+ // <div class="spinner"></div>
101
+ // <p>Загрузка...</p>
102
+ // </div>
103
+ ```
104
+
105
+ ### Интеграция с API запросами
106
+
107
+ ```javascript
108
+ import { Loading } from '@dxtmisha/functional'
109
+ import { useLoadingRef } from '@dxtmisha/functional'
110
+
111
+ export default {
112
+ setup() {
113
+ const isLoading = useLoadingRef()
114
+
115
+ const fetchUserData = async () => {
116
+ Loading.show()
117
+
118
+ try {
119
+ const response = await fetch('/api/user')
120
+ const data = await response.json()
121
+ } catch (error) {
122
+ console.error('Ошибка:', error)
123
+ } finally {
124
+ Loading.hide()
125
+ }
126
+ }
127
+
128
+ return { isLoading, fetchUserData }
129
+ }
130
+ }
131
+
132
+ // Template:
133
+ // <button @click="fetchUserData" :disabled="isLoading">
134
+ // Загрузить данные
135
+ // </button>
136
+ ```
137
+
138
+ ## Интеграция с классом Loading
139
+
140
+ Композабл тесно интегрирован с классом `Loading`:
141
+
142
+ ```javascript
143
+ import { Loading } from '@dxtmisha/functional'
144
+ import { useLoadingRef } from '@dxtmisha/functional'
145
+
146
+ // В компоненте A
147
+ const isLoading = useLoadingRef()
148
+
149
+ // В любом месте приложения
150
+ Loading.show() // isLoading.value автоматически станет true
151
+
152
+ // В другом компоненте B
153
+ Loading.hide() // isLoading.value в компоненте A автоматически обновится
154
+
155
+ // Проверка статуса
156
+ console.log(Loading.is()) // true/false
157
+
158
+ // Все компоненты с useLoadingRef() будут синхронизированы
159
+ ```