web_12.md 5.5 KB

К содержанию

Vue.js

#22 Криптономикон: refs

22 минуты

Расшифровка скринкаста

Сегодня будем решать проблему с графиком

Если размер становится очень большим, то ширина столбцов уменьшается до какого-то предела, а потом вообще выходит за размеры блока

Первый вариант, который приходит в голову, ограничить количество записей в массиве цен (метод shift удаляет первый элемент массива):

graph.value.push(t.price)
if (graph.value.length > 5) {
    graph.value.shift()
}

Но такой вариант не учитывает размер блока и выглядит плохо

Самое время познакомиться с ref

Ref, это возможность получить (в коде) ссылку на объект, который мы отрисовали в шаблоне.

Очевидно, что количество элементов в графике должно зависеть от размера блока, в котором этот график рисуется.

Чтобы найти нужный блок, можно воспользоваться панелью разработчика в браузере

  1. Кликаем правой кнопкой мыши в окне бразуера и выбираем пункт "посмотреть код"
  2. Выбираем закладку "Элементы"
  3. Активируем кнопку "Выбрать элемент", кликаем мышкой на элемент, который нам интересен (блок с графиком) и в окне элементов будет выделен элемент вёрстки, который соответствует "картинке"

  4. Находим этот блок в шаблоне и добавляем в него атрибут 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 конфликтует с именем массива с данными для графика)

  5. Затем опишем переменную, в которую при монтировании 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, а после выбора содержит ссылку на визуальный элемент

  6. Теперь, имея ссылку на визуальный элемент и зная 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 не реактивен.


Задание

  1. В нашей реализации, пока не изменится размер окна
  2. Исправить баг, когда при уменьшении размера окна элементы графика становятся узкими, пока не обновится валюта

Назад | Дальше