Beim Erstellen von Komponenten tritt häufig die Aufgabe auf, den Inhalt einer Komponente anzupassen. Zum Beispiel haben wir eine DatePicker- Komponente und müssen verschiedene Apply-Schaltflächen in verschiedenen Teilen der Webanwendung anzeigen.
Um solche Probleme zu lösen, verwendet heutzutage jede populäre Technologie das Konzept der "Slots". Angular hat ngContent , Vue , Svelte und WebComponents haben Slots. Und nur die beliebte React-Bibliothek verfügt heute nicht über ein vollwertiges Konzept für Slots.
Es gibt verschiedene Ansätze zur Lösung dieses Problems in React:
Eine Komponente kann entweder alle untergeordneten Elemente vollständig rendern oder über die React.Children- API in sie "klettern" und die untergeordneten Elemente punktuell bearbeiten
Eine Komponente kann sogenannte renderProps deklarieren und den von ihnen zurĂĽckgegebenen Inhalt an den richtigen Stellen rendern:
<MyComponent renderFooter={data => (<h1>Bye, ${data.name}</h1>)}/>
Der renderProps-Ansatz ist allgemein bekannt und weist keine grundlegenden Mängel auf. Es sei denn, es ist nicht sehr bequem, es im Vergleich zu vollwertigen Slots zu verwenden. NPM hat mehrere Bibliotheken, wie zum Beispiel React-View-Slot , aber ich denke nicht, dass sie bequem genug sind und vor allem einfach das Problem lösen.
Ich habe beschlossen, diesen schwerwiegenden Fehler zu beheben , und jetzt werde ich Ihnen sagen, wie.
Ich sehe das Ziel - ich sehe die Umsetzung nicht
Bevor Sie etwas programmieren, ist es hilfreich zu wissen, welche API Sie erhalten möchten. So sah meine Skizze des gewünschten Ergebnisses aus:
const Component = props => {
Component.NameSlot = useSlot(props.children);
return (
<div>
<h1>
<Component.NameSlot.Receiver>
Default value
</Component.NameSlot.Receiver>
</h1>
Hello {props.children}
</div>
);
};
function App() {
return (
<div>
Hello!
<Component>
Foo
<Component.NameSlot>
Bobobo
</Component.NameSlot>
</Component>
</div>
);
}Die Idee war, die erforderlichen Slots zu erstellen, die Funktionskomponente in einer statischen Eigenschaft zu speichern und sie dann auf der sendenden und der empfangenden Seite entsprechend zu verwenden.
, . – , , , -, . , , API, :
import {createSlot} from 'react-slotify';
export const MySlot = createSlot();
export const Component = ({children}) => {
return (
<div>
This component contains slot:
<MySlot.Renderer childs={children}>
This is default slot content
</MySlot.Renderer>
<div>It also renders children: {children}</div>
</div>
);
};import {Component, MySlot} from './component';
const App = () => {
return (
<div>
<Component>
<MySlot>Slotted content</MySlot>
Other content
</Component>
</div>
);
};, API, , – MySlot, {children}, , MySlot.Renderer. , JS-, :
export function createSlot() {
const Slot = ({ children, showChildren }) => {
return showChildren ? children : null;
}
const Renderer = ({ childs, children }) => {
const slotted = React.Children.toArray(childs).find(child => {
return React.isValidElement(child) && child.type === Slot;
});
if (!slotted || !React.isValidElement(slotted)) {
return children;
}
return React.cloneElement(slotted, { showChildren: true });
};
Slot.Renderer = Renderer;
return Slot;
}-, 20 . , React- , . . – Slot. , :
export function createSlot() {
const Slot = ({ children, showChildren }) => {
return showChildren ? children : null;
}
return Slot;
}, Slot – , showChildren={true}. , , Slot .
– Renderer. – -, Slot-, , showChildren={true}:
const Renderer = ({ childs, children }) => {
const slotted = React.Children.toArray(childs).find(child => {
return React.isValidElement(child) && child.type === Slot;
});
if (!slotted || !React.isValidElement(slotted)) {
return children;
}
return React.cloneElement(slotted, { showChildren: true });
};, Renderer , , Slot . .
– Renderer Slot, : <MySlot.Renderer/>.
Daher haben wir in 20 Codezeilen ein Konzept implementiert, das vielen Entwicklern in anderen Technologien wirklich gefällt und dem React fehlt.
Ich habe die fertige Implementierung als React-Slotify-Bibliothek auf GitHub und als Paket auf NPM veröffentlicht . Bereits in TypeScript und mit Unterstützung für die Parametrierung von Slots . Ich würde mich über konstruktive Kritik freuen.