Повторное использование кода Vue.js
По мере усложнения приложения, в котором львиная доля кода использует Vue.js, возникает вопрос повторного использования кода. Когда возможности расширить тот или иной компонент с помощью параметров или слотов уже не удовлетворяют всех потребностей, можно прибегнуть в другим способам.
Популярный, но все всегда правильный, способ использовать некоторую сущность добавив новые возможности – использовать наследование.
Mixin
У Vue.js для возможности наследования имеются mixin-ы. В mixin мы можем вынести данные, группу методов и даже hook-и жизненного цикла.
Например, создадим mixin-ы decrementMixin.js:
export default < data() < return < mixinData1: 1, >>, created() < console.info(`Mixin's (1) hook "created"`); >, methods: < decrement() < this.index--; >> >;
export default < data() < return < mixinData2: 2, >>, created() < console.info(`Mixin's (2) hook "created"`); >, methods: < increment() < this.index++; >, > >;
Теперь можно создать компонент, который будет использовать эти mixin-ы
>
mixinData1: >
mixinData2: >
Data: >
import incrementMixin from "@/mixins/incrementMixin" import decrementMixin from "@/mixins/decrementMixin"; export default < name: 'Mix', mixins: [ incrementMixin, decrementMixin ], data() < return < title: 'Mix', index: 0, actions: [ < text: 'Increment', handler: this.increment >, < text: 'Decrement', handler: this.decrement >, < text: 'Clear', handler: this.clear >, ] > >, created() < console.info(`Mix component hook "created"`); >, methods: < clear() < this.index = 0; >, > >
Данный компонент будет иметь методы из обоих миксинов. Обработчики created будут выполнены по очереди. Выглядеть на странице будет так:
В консоли при загрузке странице можно будет увидеть следующее:
# Mixin's (2) hook "created" # Mixin's (1) hook "created" # Mix component hook "created"
Можно видеть, что отрабатывают все hook-и жизненного цикла, что определены.
Шаблон для отображения используется, который описана в компоненте, так как в миксинах нет шаблонов. Таким образом с помощью мискинов как из частей можно создать компонент, который будет состоять из своих данных и методов и данных и методов полученных у миксинов.
Extends
Если же нужно создать потомка от существующего компонента, то для этого есть опция extends.
Допустим, у нас есть компонент Parent.vue:
export default < name: 'Parent', props: < param: < type: String, default: '' >, >, data() < return < title: 'Parent', index: 0, actions: [ < text: 'Increment', handler: this.increment >, ] > >, created() < console.info(`Parent's hook "created" for component "$"`); >, methods: < clear() < this.index = 0; >, increment() < this.index++; >, > >
Унаследуем от него ChildExtend.vue:
import Parent from "./Parent" export default < name: 'ChildExtend', extends: Parent, data() < return < title: 'ChildExtend', actions: [ < text: 'Increment', handler: this.increment >, < text: 'Decrement', handler: this.decrement >, < text: 'Clear', handler: this.clear >, ] > >, created() < console.info(`Child's hook "created"`); >, methods: < decrement() < this.index--; >> >
Шаблона собственного у него нет. Он использует шаблон родителя. Ели определим в потомке шаблон, то он полностью заменит родительский.
Вместе родительский компонент и наследник выглядят на странице так:
По своей сути extends – тот же mixin, только применяется к компоненту и позволяет наследовать шаблон.
Higher-order components (HOC)
На этом способы повторного использования кода Vue.js не заканчиваются. В сети можно встретить описание подхода Higher-order components (HOC). Он похож на паттерн “декоратор”.
Принцип такой. У исходного компонента есть некое действие (метод). А компонент, который использует исходный вызывает исходное действие и добавляет свое поведение.
Обычно в примерах HOC приводят логирование. Если вам довелось использовать такой подход в чем-то более полезном, пишите в комментариях. Я пока не вижу у данного подхода возможность широкого применения.
Итак, классический пример. Допустим у нас есть кнопка BaseButton.vue:
Можем создать функцию, которая позволяет добавить поведение. Например, здесь добавлено логирование click-ов по кнопке.
export const withLoggerButton = button => < return < name: 'ExtendedButton', render(h) < const slots = Object.keys(this.$slots).map(key =>this.$slotsJavascript повторное использование кода); return h( button, < nativeOn: < click:() => < console.log('clicked') >> >, slots ); > > >
Для лучшего понимания данного примера нужно быть знакомым с документацией по render функциям. Особенно подраздел “Подробно об объекте данных”.
После того, как была написана функция withLoggerButton мы можем где-либо создать компонент – ExtendedButton:
import BaseButton from "@/components/BaseButton"; import < withLoggerButton>from "@/withLoggerHOC"; const ExtendedButton = withLoggerButton(BaseButton);
Extended Button with logger
Расширенная кнопка будет работать точно также как и базовая, но отправлять при клике сообщение в консоль браузера.
К сожалению объект данных, передаваемый в функцию h (Сокращение createElement до h — распространённое соглашение в экосистеме Vue и обязательное для использования JSX. ) довольно ограниченный. В связи с этим в большой пользе от такого способа повторного использования кода я сильно сомневаюсь.
На этом статью завершу. Все примеры можно посмотреть и запустить склонировав код с github репозитория.
Но также я планирую продолжить изучение способов повторного использования кода в Vue.js и скоро вернусь с новой статьей.
После публикации данной статьи появились новые статьи с продолжением темы: