Низкоуровневая реализация полного цикла жизни компонента во Vue 2

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

В статье речь пойдет о низкоуровневой реализации цикла жизни компонента: объявление, монтирование в DOM, дестрой экземпляром компонента самого себя.

Мы привыкли к наиболее частому использованию компонентов: объявление, регистрация, обращение к компоненту из другого с передачей параметров.  Описываем компонент в файле componentName.vue и вызываем в шаблоне другого компонента как <component-name /> А как быть если мы хотим вызвать скажем диалоговое окно из плагина? И хотим чтобы о нашем диалоговом окне не знало все приложение, а знал только плагин? Именно с такой задачей столкнулась на рабочем проекте и собирать информацию пришлось по крупицам. Расскажу как было реализовано все перечисленное. Я делала в плагине, но это не обязательно. Этот подход можно реализовывать и в самом проекте.

Среда разработки:

  • Vue: 2

  • Nuxt: ^2.15

  • Vuetify: ^2.6

Глобальная регистрация компонента.

Внутри моего плагина notification регистрирую максимально простой компонент - диалоговое окно с переданным в плагин типом, сообщением и кнопкой закрытия. Тип определяет какого цвета сообщение. Классические: success, info, error, warning. Кнопка закрытия диалогового окна будет дестроить экземпляр компонента и удалять его из DOM. Логики у моего компонента почти не будет - только шаблон. Поэтому в компоненте сразу идет render функция. Ее задача - вернуть html-код компонента. 

   let Nf = Vue.component('notificationDialog', {

        render: function (createElement) {

	 }

})

По функции есть хорошая документация, не буду останавливаться.

Далее, описываем вложенность html тегов при помощи createElement

const alertVNode = createElement('v-alert', {

     attrs: { type: message.type, icon: false }, // атрибуты

    style: {	// стили элемента

        width: '100%'

        }

    },

    message.text) // содержимое: String или Array<VNodes>

const cardVNode = createElement('v-card', {

    class: ['pa-2', 'd-flex', 'flex-column', 'align-end',]

    },

    [alertVNode]) // Предыдущий узел добавляется как дочерний в карточку

Кто заметил что-то необычное, тот молодец. Да! createElement понимает теги Vuetify. Это здорово, т.к. экономит время на написание вложенных тегов и стилей для них! И еще одно. По этой же причине  можно менять стили на релевантные им классы. Пример ниже.

 const cardDivVNode = createElement('v-card', {

     style:{

		padding: ‘8px’,

		display: ‘flex’,

		flexDirection: ‘column’,

		alignItems: ‘end’

     },

    class: ['pa-2', 'd-flex', 'flex-column', 'align-end',]

})

То что вы видите в объектах style и class в примере выше - одно и тоже. То есть padding: ‘8px’ - все равно, что заменить классом ‘pa-2’. Расшифровывается как ‘padding all = 2*4px’. Поэтому, для единообразного дизайна - пользуюсь классами Vuetify там, где это возможно:

const cardDivVNode = createElement('v-card', {

    class: ['pa-2', 'd-flex', 'flex-column', 'align-end',]

})

Монтирование экземпляра компонента и добавление в DOM

Компонент объявлен. Далее, в логике плагина мы:

  • создаем экземпляр класса

  • монтируем его в DOM

  • и добавляем как дочерний элемент нашего корневого элемента с id=”app”

    let component = new Nf() 	// создаем экземпляр класса

    component.$mount()		// монтируем его в DOM

    document.getElementById('app')?.appendChild(component.$el) // добавляем в корень

На этом этапе все.

Дестрой экземпляра компонента, удаление из DOM

Как говорила выше, дестроить экземпляр компонента будет сам себя. В шаблоне компонента notificationDialog, в рендер функции присутствует кнопка закрытия диалогового окна:

const closeButtonVNode = createElement('v-btn', {

        attrs: {

            outlined: true, // аттрибуты Vuetify

            color: 'primary',

            block: false,

            inline: true

        },

        on: {

        // события размещаются тут

        }

}, 'Close')

У нее и будет метод onClick:

const closeButtonVNode = createElement('v-btn', {

        …

        on: {

            click: () => {

                this.$destroy() // дестроим текущий экземпляр

                this.$el?.parentNode?.removeChild(this.$el) // удаляем из DOM

            }

            }

        }, 'Close')

Заключение

У нас получилось создать компонент notificationDialog в плагине, о котором не знает основное приложение. 

  • Компонент объявляется глобально - один раз, при билдинге приложения

  • Экземпляры создаются при вызове плагина

  • Экземпляры дестроят сами себя по нажатию на кнопку.

Источник: https://habr.com/ru/articles/742310/


Интересные статьи

Интересные статьи

Как в США, так и России наибольший интерес к обеспечению безопасности личных данных граждан появился в XX веке.
Все говорят, что цифровизация помогает компаниям сокращать издержки и повышать эффективность управления бизнесом. Мы расскажем о конкретном кейсе того, как оцифровка даже одного этапа жизненного цикла...
О том, что такое пирамида как структура данных и алгоритмах по отношению к ней.
Привет, Хабр!В конце июля в JetBrains стартует очередной релизный «паровоз». На этой неделе обновились многие IDE на платформе IntelliJ, на следующей запланированы обновления наших продуктов для .NET....
Представитель нашего клиента, стек приложений которого обитает в облаке от Microsoft (Azure), обратился с проблемой: с недавнего времени часть запросов некоторых клиентов из Европы стала заве...