脚本:
<script>
function resizeIframe(obj) {
obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
}
</script>
html:
<iframe src="..." frameborder="0" scrolling="no" onload="resizeIframe(this)" />
Npmパッケージがありますreact-iframe
、しかしそれは未完成に見えます(小道具url
、width
、height
のみを受け入れます):
解決策の可能性のある部分は、load
のiframe
イベントをリッスンすることですが、Reactと互換性のある方法で行います。
React iframe
の高さをスクロール可能なコンテンツの高さに設定する方法はありますか?
私のコード:
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import Iframe from 'react-iframe'
export default class FullheightIframe extends Component {
componentDidMount() {
console.log("IFRAME DID MOUNT");
}
renderReactFrame() {
return (
<Iframe url="http://www.example.com" width="100%" height="100%" onLoad={()=>{console.log("IFRAME ON LOAD")}}></Iframe>
);
}
renderHTMLFrame() {
return (
<iframe
onLoad={(loadEvent)=>{
// NOT WORKING var frameBody = ReactDOM.findDOMNode(this).contentDocument.body; // contentDocument undefined
// NOT WORKING obj.nativeEvent.contentWindow.document.body.scrollHeight // contentWindow undefined
}}
ref="iframe"
src="http://www.example.com"
width="100%"
height="100%"
scrolling="no"
frameBorder="0"
/>
);
}
render() {
return (
<div style={{maxWidth:640, width:'100%', height:'100%', overflow:'auto'}}>
{this.renderHTMLFrame()}
</div>
);
}
}
ComponentDidMountで、スクリプトを実行して高さを設定します。 [外部コンテンツをロードする場合は、IFrameにイベントリスナーを追加して、外部コンテンツがロードされるまで待機することをお勧めします。]
componentDidMount() {
const obj = ReactDOM.findDOMNode(this);
obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
}
これを行う別の、より「反応性の高い」方法があります-高さを状態で保存します。
componentDidMount() {
const obj = ReactDOM.findDOMNode(this);
this.setState({iFrameHeight: obj.contentWindow.document.body.scrollHeight + 'px'});
}
そしてあなたのレンダリングで:
render() {
return (
<div style={{maxWidth:640, width:'100%', height:this.state.iFrameHeight, overflow:'auto'}}>
{this.renderHTMLFrame()}
</div>
);
}
これが答えですが、最初の2つの重要なことです。
render()
メソッドのルートコンポーネントである必要がありますonLoad
イベントからキャプチャする必要があります(完全にロードされている場合はiframeに一度)ここに完全なコードがあります:
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'
export default class FullheightIframe extends Component {
constructor() {
super();
this.state = {
iFrameHeight: '0px'
}
}
render() {
return (
<iframe
style={{maxWidth:640, width:'100%', height:this.state.iFrameHeight, overflow:'visible'}}
onLoad={() => {
const obj = ReactDOM.findDOMNode(this);
this.setState({
"iFrameHeight": obj.contentWindow.document.body.scrollHeight + 'px'
});
}}
ref="iframe"
src="http://www.example.com"
width="100%"
height={this.state.iFrameHeight}
scrolling="no"
frameBorder="0"
/>
);
}
}
ここで注意すべき点がいくつかあります。
componentDidMount()
のようなReactのライフサイクルメソッドを使用しようとすると、コンテンツがまだ存在しないというリスクがあります。_class WrappedFrame extends React.Component {
state = { contentHeight: 100 };
handleResize = () => {
const { body, documentElement } = this.container.contentWindow.document;
const contentHeight = Math.max(
body.clientHeight,
body.offsetHeight,
body.scrollHeight,
documentElement.clientHeight,
documentElement.offsetHeight,
documentElement.scrollHeight
);
if (contentHeight !== this.state.contentHeight) this.setState({ contentHeight });
};
onLoad = () => {
this.container.contentWindow.addEventListener('resize', this.handleResize);
this.handleResize();
}
componentWillUnmount() {
this.container.contentWindow.removeEventListener('resize', this.handleResize);
}
render() {
const { contentHeight } = this.state;
return (
<iframe
frameBorder="0"
onLoad={this.onLoad}
ref={(container) => { this.container = container; }}
scrolling="no"
src="your.source"
style={{ width: '100%', height: `${contentHeight}px` }}
title="Some Content"
/>
);
}
}
_
この例では、決定されたコンテンツの高さをコンポーネントの状態で保存し、その状態を使用してレンダリングされたiframeの高さを設定します。また、onLoad()
ハンドラー定義をコンポーネントに配置することで、すべての再レンダリングで新しいハンドラー関数を作成しないことにより、render()
のパフォーマンスをわずかに節約できます。
これまでに提案された答えはどれも私にはうまくいきませんでした。少なくとも私の場合は、setTimeout
の種類の中から短いonLoad
を実行するというハックなアプローチがその仕事をしているようです。
class SmartIFrame extends React.Component {
render() {
return <iframe srcDoc={this.props.srcDoc}
scrolling="no"
frameBorder={0}
width="100%"
onLoad = {e => setTimeout(() => {
const obj = ReactDOM.findDOMNode(this);
obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
}, 50)}/>
}
}
このnpmパッケージは何をするか、iframeのコンテンツの高さを計算するさまざまな方法を提供します
https://www.npmjs.com/package/iframe-resizer-react
このユースケースでは、次のように構成できます。
<IframeResizer
heightCalculationMethod="bodyScroll"
src="http://anotherdomain.com/iframe.html"
/>