22 минуты
Расшифровка скринкаста
Сегодня будем решать проблему с графиком
Если размер становится очень большим, то ширина столбцов уменьшается до какого-то предела, а потом вообще выходит за размеры блока
Первый вариант, который приходит в голову, ограничить количество записей в массиве цен (метод shift удаляет первый элемент массива):
graph.value.push(t.price)
if (graph.value.length > 5) {
graph.value.shift()
}
Но такой вариант не учитывает размер блока и выглядит плохо
Самое время познакомиться с ref
Ref, это возможность получить (в коде) ссылку на объект, который мы отрисовали в шаблоне.
Очевидно, что количество элементов в графике должно зависеть от размера блока, в котором этот график рисуется.
Чтобы найти нужный блок, можно воспользоваться панелью разработчика в браузере
Активируем кнопку "Выбрать элемент", кликаем мышкой на элемент, который нам интересен (блок с графиком) и в окне элементов будет выделен элемент вёрстки, который соответствует "картинке"
Находим этот блок в шаблоне и добавляем в него атрибут ref="graphRef"
<h3 class="text-lg leading-6 font-medium text-gray-900 my-8">
{{ sel.name }} - USD
</h3>
<div
ref="graphRef"
^^^^^^^^^^^
class="flex items-end border-gray-600 border-b border-l h-64">
<div
v-for="(bar, idx) in normalizedGraph"
Обратите внимание, во vue3 ссылка должна иметь уникальное имя (в оригинальном видео имя graph конфликтует с именем массива с данными для графика)
Затем опишем переменную, в которую при монтировании DOM будет записана ссылка на визуальный элемент
В текущей версии документации выглядит так:
const graphRef = useTemplateRef('graph')
Хотя можно и так (при монтировании DOM значение записывается в одноименную переменную):
const graphRef = ref(null)
Во vue3 реализация ref отличается. Во vue2, как видно из видео, все ref ссылки собираются в объект $ref, а во vue3 каждая ссылка записывается в одноимённую переменную.
Мы можем добавить логи вывода значения этой переменной при формировании графика
graph.value.push(t.price)
if (graph.value.length > 5) {
graph.value.shift()
}
console.log('graphRef:', graphRef.value)
Пока не выбран тикер, значение равно null, а после выбора содержит ссылку на визуальный элемент
Теперь, имея ссылку на визуальный элемент и зная js и css, можем получить его ширину (сразу заворачиваем в вычисляемое свойство)
const maxGraphElements = computed(() => {
if (graphRef.value == null) return 0
return graphRef.value.clientWidth / 38
})
И используем это свойство при формировании графика
if (graph.value.length > maxGraphElements.value) {
graph.value.shift()
}
Работает!!!
Но при изменении размеров экрана количество не пересчитывается. Ref не реактивен.
Учёт изменения размеров браузера
Сначала переделываем метод расчета количества элементов (вместо computed)
function calculateMaxGraphElements () {
// реализована защита от null (когда график не отображается)
maxGraphElements.value = (graphRef.value?.clientWidth ?? 0) / 38
}
Не забываем описать переменную maxGraphElements
Используем подписку на события окна (в видео записано в метод onMounted)
window.addEventListener(
'resize',
calculateMaxGraphElements)
Не забываем отписаться от события в методе onBeforeUnmount
onBeforeUnmount(() => {
window.removeEventListener(
'resize',
calculateMaxGraphElements)
})
В текущей реализации размер графика равен
0, пока мы не поменяем размер окна. Пока считаем это фичей и исправим на следующем занятии
Заключение
Задание
38 (размер элемента графика) используя дополнительный ref для элемента графика