Автор: markzzw Время: 2019-12-19 Оригинальный адрес:исходный адрес
Введение
Знаете ли вы предшественника настоящего и реагирующего портала на него? Эта статья расскажет вам ответ.
содержание
- Что такое Portal и оригинал
- Реагировать портал сейчас
- Предыдущий портал React
- Сценарии использования портала
- использованная литература
Что такое портал
Portal
Предоставляет отличное решение для рендеринга дочерних узлов в узлы DOM, которые существуют вне родительского компонента. Одинportal
Типичный вариант использования — когда родительский компонент имеетoverflow: hidden
илиz-index
при стилизации, но вам нужно, чтобы дочерний компонент мог визуально «выпрыгивать» из своего контейнера. Например, диалоги, всплывающие подсказки и всплывающие подсказки.
ВышеReact
изофициальное объяснение
с картинками
React-портал сейчас
существуетReact16
Позже,React
обеспечивает функциюReactDOM.createPortal(child, container)
сделатьReact 子元素
к указанномуcontainer
, очень удобен в использовании;
Модальный пример с официального сайта React
Это уже должно быть известноportal
использование
const modalRoot = document.getElementById('modal-root');
class Modal extends React.Component {
constructor(props) {
super(props);
this.el = document.createElement('div');
}
componentDidMount() {
modalRoot.appendChild(this.el);
}
componentWillUnmount() {
modalRoot.removeChild(this.el);
}
render() {
return ReactDOM.createPortal(
this.props.children,
this.el,
);
}
}
Предыдущий React-портал
Затем вReact
не предоставленcreatePortal()
когда,Portal
Как этого добиться? Здесь мы будем использовать другой методReactDOM.render(element, container[, callback])
;
Пример использования ReactDOM.render
interface PortalProps extends CommonComponentProps {
getContainer?: Function;
visible?: boolean;
}
class Portal extends React.Component<PortalProps> {
mountDom: HTMLElement;
container: HTMLElement;
constructor(props:PortalProps) {
super(props);
this.mountDom = document.createElement('div');
this.container = props.getContainer
? props.getContainer()
: window.document.body;
}
componentDidMount() {
this.container.appendChild(this.mountDom);
}
componentWillUnmount() {
if (this.mountDom) {
this.container.removeChild(this.mountDom);
}
}
getVisible = () => {
if ('visible' in this.props) {
return this.props.visible;
}
return true;
}
render() {
const { children } = this.props;
if (this.container && this.getVisible()) {
if (createPortal) {
return createPortal(children, this.mountDom);
}
ReactDom.render(children, this.mountDom);
}
return null;
}
}
export default Portal;
даже в некоторыхкодтакже появляется при использованииReactDOM.unstable_renderSubtreeIntoContainer(paren,component,container,callback);
Это вcreatePortal
Когда решение не появляется, некоторые решения;
Сценарии использования портала
Наиболее известным является созданиеModal
илиDialog
компонент;
export interface DialogWrapperProps extends DialogProps {
visible?: boolean;
getContainer?: () => void;
}
class DialogWrapper extends Component<DialogWrapperProps>{
render() {
const { getContainer, children, onClose, visible } = this.props;
if (visible) {
return (
<Portal
visible={visible}
getContainer={getContainer}
>
<Dialog
onClose={onClose}
>
{children}
</Dialog>
</Portal>
);
}
return null;
}
}
export default DialogWrapper;
При создании выпадающего меню Dropdown
Потому что вы можете монтировать необходимые файлы на любом узлеReact 元素
, поэтому нам также нужно будет использовать его в раскрывающемся компонентеPortal
помогите нам сделать это;
class Trigger extends Component<TriggerProps, {
triggerVisible: boolean
}> {
popupContainer: HTMLElement;
node: any;
popupRef: any;
clickPopupOutSideFun: void | null;
constructor(props: TriggerProps) {
}
getPortalContainer = () => {...};
creatPopupContainer = () => {...}
getContainer = () => {...};
render() {
const {
children,
className
} = this.props;
const {
triggerVisible
} = this.state;
const trigger = React.cloneElement(children, {
className: classNames('pb-dropdown-trigger', className),
ref: composeRef(this.node, (children as any).ref) // compose this component ref and children refs
});
let portal: React.ReactElement | null = null;
if (triggerVisible) {
portal = (
<Portal
key="portal"
getContainer={this.getContainer}
>
{this.getPortalContainer()}
</Portal>
);
}
const newChildProps: HTMLAttributes<HTMLElement> & { key: string } = { key: 'trigger' };
const child = (
<div>
{trigger}
{portal}
</div>
);
this.genNewChildren(newChildProps);
const newChild = React.cloneElement(child, {
...newChildProps,
ref: composeRef(this.node, (children as any).ref)
});
return newChild;
}
}
export default Trigger;