В мире фронтенда принято переиспользовать один и тот же компонент множество раз. BEM-блоки, компонентный подход – всё об этом. Это как возвести здание из кирпичиков.
Допустим, нам нужно использовать одну и ту же функциональность, но при этом иметь возможноть задавать компоненту разные html-теги. И тогда хочется сделать что-то подобное:
render() {
return <[this.props.tag] />
}
Передавать через props
нужный тег. Без жёсткой привязки. Динамически.
Решение для React
В JSX данный выше код вызовет ошибку на этапе компиляции. Дело в том, что нам требуются имена элементов, начинающиеся с заглавной буквы. То есть подойдёт следующая запись:
render() {
const TagName = this.props.tag
return <TagName />
}
Альтернативный способ потребует импорта компонентов:
import React, { Component } from 'react';
import FooComponent from './foo-component';
import BarComponent from './bar-component';
export default class CustomComponent extends Component {
components = {
foo: FooComponent,
bar: BarComponent
}
render() {
const TagName = this.components[this.props.tag || 'foo']
return <TagName />
}
}
Подключаем извне как обычно:
import React, { Component } from 'react';
import { CustomComponent } from './custom-component';
export default class App extends Component {
render() {
return <CustomComponent tag="foo" />
}
}
Решение для Vue.js
С Vue.js в этом плане тоже всё отлично. И для этого также используется функция render
.
import Vue from 'vue';
Vue.component('custom-component', {
name: 'custom-component',
render(createElement) {
return createElement(
this.tag, // tag
this.$slots.default // array of children
);
},
props: {
tag: { type: String, required: true },
}
});
Готово. Теперь можно переиспользовать и задавать свои html-теги.
<custom-component tag="section">
<p>Hello</p>
</custom-component>