Составление против наследования
React имеет мощную модель составления, и мы рекомендуем использовать составление вместо наследования для повторного использования кода между компонентами.
В этом разделе мы рассмотрим несколько проблем, в которых разработчики, новые в React, часто прибегают к наследованию, и покажем, как мы можем решить их с помощью составления.
Содержимое
Некоторые компоненты не знают своих дочерних элементов заранее. Это особенно распространено для компонентов, таких как Sidebar или Dialog, которые представляют собой обобщенные «боксы».
Мы рекомендуем, чтобы такие компоненты использовали специальный children атрибут для прямого передачи дочерних элементов в их вывод:
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
} Это позволяет другим компонентам передавать произвольные дочерние элементы, вкладывая JSX:
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
} Все, что находится внутри <FancyBorder> тега JSX, передается в компонент FancyBorder в виде children атрибута. Поскольку FancyBorder отображает {props.children} внутри <div>, переданные элементы отображаются в конечном выводе.
Хотя это менее распространено, иногда вам может потребоваться несколько «дырок» в компоненте. В таких случаях вы можете разработать собственную конвенцию вместо использования children.
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);
}
function App() {
return (
<SplitPane
left={
<Contacts /> }
right={
<Chat /> } />
);
} Элементы React, такие как <Contacts /> и <Chat />, — это просто объекты, поэтому вы можете передавать их как атрибуты, как и любые другие данные. Этот подход может напомнить вам о «слотах» в других библиотеках, но в React нет ограничений на то, что можно передать как атрибуты.
Специализация
Иногда мы рассматриваем компоненты как «специальные случаи» других компонентов. Например, мы можем сказать, что WelcomeDialog является специальным случаем Dialog.
В React это также достигается с помощью составления, где более «специализированный» компонент отображает более «обобщенный» и настраивает его с помощью атрибутов:
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
function WelcomeDialog() {
return (
<Dialog title="Welcome" message="Thank you for visiting our spacecraft!" />
);
} Составление работает одинаково хорошо для компонентов, определенных как классы:
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
{props.children}
</FancyBorder>
);
}
class SignUpDialog extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSignUp = this.handleSignUp.bind(this);
this.state = {login: ''};
}
render() {
return (
<Dialog title="Mars Exploration Program"
message="How should we refer to you?">
<input value={this.state.login} onChange={this.handleChange} />
<button onClick={this.handleSignUp}>
Sign Me Up!
</button>
</Dialog>
);
}
handleChange(e) {
this.setState({login: e.target.value});
}
handleSignUp() {
alert(`Welcome aboard, ${this.state.login}!`);
}
} А что насчет наследования?
В Facebook мы используем React в тысячах компонентов, и мы не нашли ни одного случая, в котором мы бы рекомендовали создавать иерархии наследования компонентов.
Атрибуты и составление дают вам всю необходимую гибкость для настройки внешнего вида и поведения компонента явным и безопасным способом. Помните, что компоненты могут принимать произвольные атрибуты, включая примитивные значения, элементы React или функции.
Если вы хотите повторно использовать не относящиеся к пользовательскому интерфейсу функции между компонентами, мы рекомендуем извлечь их в отдельный модуль JavaScript. Компоненты могут импортировать его и использовать эту функцию, объект или класс, не расширяя его.
Полезная ли эта страница?
© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://17.reactjs.org/docs/composition-vs-inheritance.html