让页面中iframe 或者 div 高度自适应

本文介绍如何通过JavaScript代码获取页面高度并调整iframe或div的高度,以实现页面自适应布局,减少空白并兼容不同浏览器。同时,解决了一个页面在增加下拉列表搜索结果时高度异常增加的问题。
我们在项目中的开发标准分辨率是1024*768,但是在当今大屏幕显示器越来越普及的情况下,我们需要尽量让整个页面铺满,少留空白,同时兼容各种浏览器。在网上搜了一位高手朋友的代码,再此感谢那位仁兄。
要实现 iframe 或者 div 在 页面中的高度自适应,我们需要做两件事情:
1 取得 页面的高度 ,JS代码如下
/*
*获得页面的高度、宽度,兼容各种浏览器的方法
*@author fengf
*@createDate 2011-10-25
*/
function ___getPageSize() {
var xScroll, yScroll;
if (window.innerHeight && window.scrollMaxY) {
xScroll = window.innerWidth + window.scrollMaxX;
yScroll = window.innerHeight + window.scrollMaxY;
} else if (document.body.scrollHeight > document.body.offsetHeight){
// all but Explorer Mac
xScroll = document.body.scrollWidth;
yScroll = document.body.scrollHeight;
} else {
// Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
xScroll = document.body.offsetWidth;
yScroll = document.body.offsetHeight;
}
var windowWidth, windowHeight;
if (self.innerHeight) {
// all except Explorer
if(document.documentElement.clientWidth){
windowWidth = document.documentElement.clientWidth;
} else {
windowWidth = self.innerWidth;
}
windowHeight = self.innerHeight;
} else if (document.documentElement && document.documentElement.clientHeight) {
// Explorer 6 Strict Mode
windowWidth = document.documentElement.clientWidth;
windowHeight = document.documentElement.clientHeight;
} else if (document.body) {
// other Explorers
windowWidth = document.body.clientWidth;
windowHeight = document.body.clientHeight;
}
// for small pages with total height less then height of the viewport
if(yScroll < windowHeight){
pageHeight = windowHeight;
} else {
pageHeight = yScroll;
}
// for small pages with total width less then width of the viewport
if(xScroll < windowWidth){
pageWidth = xScroll;
} else {
pageWidth = windowWidth;
}
arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight);
return arrayPageSize;
};

2 根据页面的高度,去设置 页面中 iframe 或者 div 的高度,这里有个div 或者iframe 的最小高度,iframe的高度一般等于页面的高度减去某一个固定高度,如下面300就是除去div后其他组件的固定高度
function resizeDivOrIFrame(){
document.getElementById("targetDiv").style.height = ___getPageSize[1]-300;
}

3 在页面中 启动一个线程,不断的调用
window.setInterval("resizeDivOrIFrame()", 200);

ps:遇到一个奇怪的问题: 有一个页面是一个带下拉列表搜索的,结果列表的高度一直在增加,不知其解。
<think>我们被要求解决Vue3中实现iframe高度自适应的问题。根据引用内容,有几种方法可以实现: 1. 引用[1]和[3]提供了在iframe加载完成后,通过JavaScript动态调整iframe高度的方案。 2. 引用[4]则通过设置外层容器的高度,并监听窗口变化来调整高度,但并没有根据iframe内容调整。 用户的需求是让iframe高度根据内容自适应,所以我们应该采用第一种方案:在iframe的load事件中,获取其内容的高度,然后设置iframe高度。 然而,我们需要注意跨域问题:如果iframe加载的是外部资源(不同域),那么由于同源策略,我们将无法访问iframe内部的document对象。但根据引用[1]和[3],他们引用的是本地文件(放在public/static下),所以同源,可以访问contentDocument。 因此,解决方案步骤: 1. 在模板中,给iframe设置一个id,并设置初始高度(可以设置一个默认高度或者用min-height)。 2. 在onMounted生命周期钩子中,获取该iframe元素,并为其添加load事件监听器。 3. 在load事件中,通过iframe.contentDocument获取内部文档,然后计算文档的高度(引用[1]和[3]都提供了计算方式,我们可以综合:取scrollHeight、offsetHeight等最大值)。 4. 将计算得到的高度设置为iframe高度。 注意:由于iframe加载需要时间,所以我们在load事件触发时再计算高度。但有时可能内部还有异步加载的内容,所以引用[3]使用了setTimeout来延迟获取,这是一个可选步骤。 另外,引用[4]提到了加载状态,我们可以考虑在加载过程中显示loading,加载完成(包括高度调整完成)后隐藏loading。 下面我们给出一个综合方案: 步骤: 1. 在public目录下放置需要引用的HTML文件(如果是本地文件)。 2. 在组件模板中,使用iframe并设置src,同时设置一个id以便获取元素。 3. 在setup中使用ref来存储高度,并设置一个loading状态。 4. 在onMounted中获取iframe元素并添加load事件监听。 5. 在load事件处理函数中,计算内容高度,并设置iframe高度,同时隐藏loading。 代码示例: ```vue <template> <div> <!-- 加载状态提示 --> <div v-if="loading">Loading...</div> <iframe ref="iframeRef" :src="iframeSrc" frameborder="0" scrolling="no" :style="{ width: '100%', height: iframeHeight }" ></iframe> </div> </template> <script setup> import { ref, onMounted } from 'vue'; const iframeSrc = '/static/your-page.html'; // 假设放在public/static下 const iframeRef = ref(null); const iframeHeight = ref('500px'); // 初始高度,可以设置一个默认值 const loading = ref(true); // 计算内容高度的函数 function getContentHeight(doc) { const body = doc.body; const html = doc.documentElement; // 获取文档内容的最大高度 const height = Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight ); return height; } onMounted(() => { const iframe = iframeRef.value; iframe.addEventListener('load', () => { // 由于iframe加载完成后,内部文档可能还在渲染,所以稍等片刻 setTimeout(() => { try { // 获取iframe内部的document对象 const doc = iframe.contentDocument || iframe.contentWindow.document; if (doc) { const height = getContentHeight(doc); iframeHeight.value = `${height}px`; } } catch (e) { // 处理可能的跨域问题 console.error('无法访问iframe内部文档:', e); // 如果跨域,可以采用其他方式,比如postMessage通信,但需要内部页面配合 } loading.value = false; }, 100); // 延迟100毫秒,确保内容完全渲染 }); }); </script> ``` 注意:如果iframe的内容是跨域的,那么访问contentDocument会抛出异常。这时,我们无法直接获取内容高度。解决方案通常是通过postMessage与iframe内部页面进行通信,让内部页面在加载完成后将高度信息发送给父页面。但这需要内部页面的配合。 如果用户引用的外部页面不受控制,则无法实现完美自适应,只能设置固定高度或者通过其他方式估算。 根据引用[1]和[3],他们引用的是本地文件,所以不存在跨域问题。因此,上述方案可行。 另外,如果iframe内部内容高度会动态变化(例如异步加载内容),我们可能还需要使用MutationObserver来监听内容变化并重新调整高度。但这是一个更高级的话题,如果用户需要,可以在相关问题中提出。 最后,我们生成相关问题。 </think> ### Vue3实现iframe高度自适应方案 在Vue3中实现iframe高度自适应主要涉及以下步骤(基于提供的引用内容): #### 解决方案步骤 1. **基本iframe结构** 在模板中创建iframe并设置初始样式: ```vue <template> <iframe ref="myIframe" src="/static/your-page.html" frameborder="0" scrolling="no" style="width:100%; min-height:300px;" ></iframe> </template> ``` 2. **动态高度计算** 在setup中使用生命周期钩子: ```javascript import { ref, onMounted } from 'vue' const myIframe = ref(null) const iframeHeight = ref('300px') // 初始高度 onMounted(() => { const iframe = myIframe.value iframe.addEventListener('load', () => { try { const doc = iframe.contentDocument || iframe.contentWindow.document // 获取内容实际高度 const height = Math.max( doc.body.scrollHeight, doc.body.offsetHeight, doc.documentElement.scrollHeight, doc.documentElement.offsetHeight ) iframeHeight.value = `${height}px` iframe.style.height = `${height}px` // 立即生效 } catch (e) { console.error('跨域访问受限', e) } }) }) ``` 3. **优化处理(可选)** - **防抖处理**:添加延时确保内容完全加载 ```javascript setTimeout(() => { // 计算高度代码 }, 100) // 适当延时 ``` - **加载状态**(引用[4]方案): ```vue <div v-if="loading">加载中...</div> <iframe v-else ... /> ``` #### 关键注意事项 1. **跨域限制** 若iframe加载外部域名内容,会因同源策略无法访问`contentDocument`。解决方案: - 使用`postMessage`进行跨域通信 - 服务端代理使域名同源 2. **动态内容处理** 如果iframe内容会动态变化,需添加监听: ```javascript new MutationObserver(() => { // 重新计算高度 }).observe(doc.body, { childList: true, subtree: true }) ``` 3. **响应式适配**(引用[4]方案) 窗口大小变化时调整: ```javascript window.addEventListener('resize', () => { // 重新计算高度 }) ``` #### 完整示例组件 ```vue <template> <iframe ref="iframeRef" :src="src" frameborder="0" scrolling="no" :style="{ width: '100%', height: iframeHeight }" /> </template> <script setup> import { ref, onMounted } from 'vue' const props = defineProps({ src: { type: String, required: true } }) const iframeRef = ref(null) const iframeHeight = ref('400px') // 默认高度 const calcHeight = (doc) => { return Math.max( doc.body.scrollHeight, doc.documentElement.scrollHeight ) + 'px' } onMounted(() => { const iframe = iframeRef.value iframe.onload = () => { setTimeout(() => { try { const doc = iframe.contentDocument || iframe.contentWindow.document iframeHeight.value = calcHeight(doc) } catch (e) { console.warn('高度计算受限', e) // 降级方案:使用默认高度 } }, 200) } }) </script> ``` ### 常见问题及解决 1. **高度跳动问题** 初始设置`min-height`过渡,加载完成后再精确设置高度 2. **内容延迟加载** 使用`setTimeout`分层级延迟计算(如引用[3]中的双重延时) 3. **移动端适配** 添加`viewport`元标签: ```html <meta name="viewport" content="width=device-width, initial-scale=1.0"> ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值