Директива ref

Директива ref в библиотеке FAST Element является инструментом для прямого получения ссылок на DOM-элементы или компоненты внутри шаблона. Она позволяет управлять элементами после их создания, предоставляя доступ к их свойствам, методам и событиям без необходимости поиска через стандартные DOM-методы (querySelector, getElementById и т.п.).


Основы использования ref

Синтаксис директивы прост: в шаблоне FAST Element к элементу или компоненту добавляется атрибут ref с функцией, которая принимает один аргумент — ссылку на DOM-узел или компонент.

import { FASTElement, html, ref } from "@microsoft/fast-element";

class MyComponent extends FASTElement {
    buttonElement;

    handleButtonRef = (el) => {
        this.buttonElement = el;
    }
}

MyComponent.template = html<MyComponent>`
    <button ${ref(x => x.handleButtonRef)}>Нажми меня</button>
`;

В этом примере функция handleButtonRef получает ссылку на элемент <button> и сохраняет её в свойство buttonElement. После этого можно напрямую работать с кнопкой в методах компонента, например вызывать методы, изменять атрибуты или добавлять обработчики событий.

Ключевой момент: функция, переданная в ref, вызывается один раз при создании элемента и затем при удалении элемента с передачей null. Это позволяет безопасно освобождать ссылки на элементы.


Работа с компонентами

ref не ограничивается стандартными HTML-элементами. Она также работает с кастомными элементами, созданными на основе FAST Element или других веб-компонентов.

class CustomInput extends FASTElement {
    focusInput() {
        this.shadowRoot.querySelector("input").focus();
    }
}

class FormComponent extends FASTElement {
    inputRef;

    handleInputRef = (el) => {
        this.inputRef = el;
    }
}

FormComponent.template = html<FormComponent>`
    <custom-input ${ref(x => x.handleInputRef)}></custom-input>
    <button @click="${x => x.inputRef.focusInput()}">Фокус на инпут</button>
`;

В этом примере ref позволяет вызвать метод кастомного компонента напрямую, без необходимости искать его в DOM.


Динамическая привязка

ref может быть использована и для динамических элементов, например, в циклах repeat. Каждый элемент получает собственную ссылку, что позволяет управлять отдельными экземплярами.

import { repeat } from "@microsoft/fast-element";

class ItemList extends FASTElement {
    items = ["A", "B", "C"];
    itemRefs = [];

    handleItemRef = (el, index) => {
        this.itemRefs[index] = el;
    }
}

ItemList.template = html<ItemList>`
    <ul>
        ${repeat(x => x.items, html<ItemList>`
            <li ${ref((el, c, index) => x.handleItemRef(el, index))}>${x => x}</li>
        `)}
    </ul>
`;

После рендера массив itemRefs содержит ссылки на все <li> элементы, позволяя программно управлять их состоянием или стилями.


Обнуление ссылок

Важно учитывать, что при удалении элемента из DOM функция, переданная в ref, вызывается с аргументом null. Это позволяет корректно освобождать ресурсы и предотвращает утечки памяти:

handleButtonRef = (el) => {
    this.buttonElement = el;
    if (!el) {
        console.log("Элемент удалён из DOM");
    }
};

Отличия ref от стандартных методов доступа к DOM

  1. Автоматическая синхронизация с жизненным циклом элемента. Ссылки обнуляются при удалении элемента.
  2. Работа с кастомными элементами и компонентами без поиска через DOM.
  3. Совместимость с динамическими шаблонами и циклическими структурами (repeat).
  4. Типизация в TypeScript. Поскольку ref сохраняет ссылки в свойствах класса, можно использовать строгую типизацию.

Рекомендации по использованию

  • Использовать ref для элементов, с которыми требуется прямое взаимодействие (изменение состояния, вызов методов).
  • Для простых отображений без необходимости манипулирования DOM предпочтительнее обходиться стандартными привязками (${x => x.value}), чтобы не усложнять код.
  • В циклах repeat контролировать индекс, чтобы избежать перезаписи ссылок при обновлении списка.
  • Освобождать ссылки в ref при удалении элементов, если нужно управлять ресурсами вручную (например, таймерами или слушателями событий).

ref является ключевым инструментом для эффективного управления DOM в FAST Element, обеспечивая прямой доступ к элементам и компонентам при строгой интеграции с жизненным циклом шаблонов. Она сочетает удобство с безопасностью, особенно при работе с динамическими интерфейсами и кастомными элементами.