我有一个显示数据的组件。我必须在新窗口中单击父组件的按钮/链接打开此组件。
-Wall
我不知道如何调用另一个组件并在新的指定窗口中显示它。
实际上我需要向该子组件发送一个道具,用它从数据库中获取数据并进行渲染。
答案 0 :(得分:6)
您可以使用ReactDOM.createPortal
在新窗口中呈现组件David Gilbertson在post中解释:
class MyWindowPortal extends React.PureComponent { constructor(props) { super(props); // STEP 1: create a container <div> this.containerEl = document.createElement('div'); this.externalWindow = null; } render() { // STEP 2: append props.children to the container <div> that isn't mounted anywhere yet return ReactDOM.createPortal(this.props.children, this.containerEl); } componentDidMount() { // STEP 3: open a new browser window and store a reference to it this.externalWindow = window.open('', '', 'width=600,height=400,left=200,top=200'); // STEP 4: append the container <div> (that has props.children appended to it) to the body of the new window this.externalWindow.document.body.appendChild(this.containerEl); } componentWillUnmount() { // STEP 5: This will fire when this.state.showWindowPortal in the parent component becomes false // So we tidy up by closing the window this.externalWindow.close(); } }
答案 1 :(得分:4)
此答案基于David Gilbertson's post。它已被修改以在Edge中工作。为了使它在Edge div
和style
中起作用,元素必须为created with the window into which they will be rendered。
class MyWindowPortal extends React.PureComponent {
constructor(props) {
super(props);
this.containerEl = null;
this.externalWindow = null;
}
componentDidMount() {
// STEP 1: Create a new window, a div, and append it to the window. The div
// *MUST** be created by the window it is to be appended to (Edge only)
this.externalWindow = window.open('', '', 'width=600,height=400,left=200,top=200');
this.containerEl = this.externalWindow.document.createElement('div');
this.externalWindow.document.body.appendChild(this.containerEl);
}
componentWillUnmount() {
// STEP 2: This will fire when this.state.showWindowPortal in the parent component
// becomes false so we tidy up by just closing the window
this.externalWindow.close();
}
render() {
// STEP 3: The first render occurs before componentDidMount (where we open the
// new window) so container may be null, in this case render nothing.
if (!this.containerEl) {
return null;
}
// STEP 4: Append props.children to the container <div> in the new window
return ReactDOM.createPortal(this.props.children, this.containerEl);
}
}
完整的修改源可以在这里https://codepen.io/iamrewt/pen/WYbPWN
答案 2 :(得分:0)
您不会直接打开该组件。您需要一个显示该组件的新页面/视图。当您打开窗口时,您将指向相应的URL。
至于大小,你在open的第三个参数中将它作为一个字符串提供,你实际上是正确的:
window.open('http://example.com/child-path','Data','height=250,width=250');
但请注意,由于各种原因,浏览器可能不会考虑您的宽度和高度请求。出于这个原因,如果它打开的空间比你想要的大,那么也可以使用适当的CSS来获得合适大小的空间。
答案 3 :(得分:0)
推荐的答案很棒!
只是在这里保留功能组件版本,以防将来人们在搜索它。
const WindowScope = (props) => {
const containerEl = useRef(document.createElement("div"));
const externalWindow = useRef(null);
useEffect(() => {
externalWindow.current = window.open(
"",
"",
"width=600,height=400,left=200,top=200"
);
const currentWindow = externalWindow.current;
if (currentWindow) {
currentWindow.document.body.appendChild(containerEl.current);
return () => currentWindow.close();
}
}, []);
return createPortal(props.children, containerEl.current);
};
答案 4 :(得分:0)
添加到当前答案 - 将样式从原始窗口复制到弹出窗口,您可以:
function copyStyles(src, dest) {
Array.from(src.styleSheets).forEach(styleSheet => {
dest.head.appendChild(styleSheet.ownerNode.cloneNode(true))
})
Array.from(src.fonts).forEach(font => dest.fonts.add(font))
}
然后添加
copyStyles(window.document, popupWindow.document);
在调用 window.open
之后,并且一旦 ref 被初始化