iframe自适应高度

参考文章 -  iframe

                   iframe优缺点

                  iframe黑魔法

前言:

  首先要知道iframe的基本概念,iframe就是一个可以引入其他网页的框架,可以进行下面的设置:

<iframe src="http://www.baidu.com" frameborder="0" width="500" height="300" scrolling="no"></iframe>

  这里定义了iframe的src、宽、高,并且使得iframe不能scroll。

  

  其次,window.top对象指向的是浏览器最顶层的窗口。 window.top对象指向的是当前窗口,可能是最顶层窗口,也可能是其中的一个框架。我们可以使用window.top.location属性来得到最顶层窗口的的url。

  

  最后,要知道iframe的高度是不能自适应高度的,其高度和宽度没有固定的规律, 所以我们这里需要解决的问题就是 iframe 的高度动态适应的问题。

实现:

  希望实现高度自适应,我们根据iframe的一些特性,分为下面的几种情况:

  • 同域实现高度自适应。 如 www.a.com/a.html 与 www.a.html/b.html ,这就是同域的情况。
  • 跨域实现高度自适应
    • 跨子域实现。 如first.a.com/a.thml 与 second.a.com/b.html, 这就是跨子域的情况。
    • 完全跨域实现。 如www.a.com/a.html 与 www.b.com/b.html , 这就是完全跨域的情况。 

 个人理解: 同域是同域名,而同源是同域名、端口号、协议,两个是不同的。

 

同域实现高度自适应

方法1:父级页面获取子级页面的高度 给元素设置高度

参考文章

这方法是用在父级页面里的,通过获取子级页面的高度给iframe设置高度

比如a.html中以iframe的形式嵌入了b.html,希望b.html可以是自适应的高度。 

b.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>b</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    body {
      background-color: #ccc;
    }
  </style>
</head>
<body>
  <h2>这是b页面</h2>
  <h2>这是b页面</h2>
  <h2>这是b页面</h2>
  <h2>这是b页面</h2>
  <h2>这是b页面</h2>
  <h2>这是b页面</h2>
  <h2>这是b页面</h2>
  <h2>这是b页面</h2>
  <h2>这是b页面</h2>
  <h2>这是b页面</h2>
  <h2>这是b页面</h2>
</body>
</html>

a.html 如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>a</title>
</head>
<body>
  <p>这是a页面</p>
  <iframe src="./b.html" frameborder="1"></iframe>
  <script>
    var ifr = document.querySelector('iframe');
    ifr.onload = function () {
      var oHeight = Math.max(ifr.contentWindow.document.documentElement.offsetHeight, ifr.contentWindow.document.body.offsetHeight);
      var cHeight = Math.max(ifr.contentWindow.document.documentElement.clientHeight, ifr.contentWindow.document.body.clientHeight);
      var height = Math.max(oHeight, cHeight);
      ifr.style.height = height + 'px'
    }
  </script>
</body>
</html>

即通过ifr.contentWindow获取到window, 而document是window的属性,所以我们就可以通过window.document获取到了,后面的也就简单了。  

方法二:子级页面给父级页面元素设置高度

  又因为这是没有跨域存在的,所以iframe也可以通过 window.parent 来访问父document。 比如c中有iframe的d,希望d可以自适应,那么c的代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>c</title>
</head>
<body>
  <p>这是c页面</p>
  <iframe src="./d.html" frameborder="1"></iframe>
</body>
</html>

d.html 如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>d</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    body {
      background-color: #ccc;
    }
  </style>
  <script>
    window.onload = function () {
      var parentDoc = window.parent.document;
      var oHeight = Math.max(document.documentElement.offsetHeight, document.body.offsetHeight);
      var cHeight = Math.max(document.documentElement.clientHeight, document.body.clientHeight);
      var height = Math.max(oHeight, cHeight);
      parentDoc.querySelector('iframe').style.height =  height + 'px';
    }
  </script>
</head>
<body>
  <h2>这是d页面</h2>
  <h2>这是d页面</h2>
  <h2>这是d页面</h2>
  <h2>这是d页面</h2>
  <h2>这是d页面</h2>
  <h2>这是d页面</h2>
  <h2>这是d页面</h2>
  <h2>这是d页面</h2>
  <h2>这是d页面</h2>
  <h2>这是d页面</h2>
  <h2>这是d页面</h2>
</body>
</html>

即我们通过window.parent就可以访问到父window,然后进而就可以访问到document了,那么document这个dom结构的任何东西我们就都可以访问的到了。 

这些是同域的情况,那么跨域的情况呢? 

 跨域实现高度自适应 --- 跨子域的高度自适应

  对于跨子域而言,实际上就非常简单了,我们可以直接通过设置 document.domain ,进而就可以使用之前的没有跨域的方式进行通信了,这里不做过多的赘述。

  比如 'a.jd.com/3.html' 嵌入了 'b.jd.com/4.html',这种跨子域的页面。

  3.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8' />
    <title>1.html</title>
    <script type="text/javascript">
        document.domain = 'jd.com'
    </script>
  </head>
  <body>
     <iframe id="ifr" src="b.jd.com/4.html" frameborder="0" width="100%"></iframe>
  </body>

 4.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>2.html</title>
    <script type="text/javascript">
        document.domain = 'jd.com'
    </script>
  </head>
  <body>
     <p>这是一个ifrmae,嵌入在3.html里 </p>
     <p>根据自身内容调整高度</p>
     <p>a</p><p>a</p><p>a</p><p>a</p><p>a</p><p>a</p><p>a</p><p>a</p>
<script>
    // 计算页面的实际高度,iframe自适应会用到
    function calcPageHeight(doc) {
        var cHeight = Math.max(doc.body.clientHeight, doc.documentElement.clientHeight)
        var sHeight = Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight)
        var height  = Math.max(cHeight, sHeight)
        return height
    }
    window.onload = function() {
        var height = calcPageHeight(document)
        parent.document.getElementById('ifr').style.height = height + 'px'     
    }
</script>
  </body>
</html>

注意: 不难发现,和同域相比,这里只要在两个html中添加相同的 document.domain 就可以了。其他没有区别。

 跨域实现高度自适应 --- 完全跨域的高度自适应

     首先大概说一下思路,比如我们需要在localhost: 8081/a.html这个html文件中添加localhost:8088/b.html这个html文件,希望让跨域的b.html文件高度自适应,由于跨域,所以我们没有办法直接获取到localhost: 8088这个域下的文件, 但是我们可以在b.html中引入一个 localhost: 8081/c.html,通过c.html,我们就可以利用parent.parent访问到a了,这样,就可以来设置a中b的高度了。但是在c.html中怎么才能拿到b.html的高度呢? 显然这又是跨域的,不能拿到,但是,我们可以通过在iframe引入c的时候,在后面添加一个查询字符串,这样,c就可以通过location来拿到高度,通过parent.parent进行设置了,这并不会对页面产生什么影响。

 分别有以下资源:

 这四个资源的关系如下所示:

  • A中 嵌入了 C, 且A和C是跨域的。
  • C中 嵌入了 B, 虽然C和B不同域,但A和B是同域的。
  • C中 嵌入了 D.js,  D.js 放在了和A同域的项目里。

我们通过一个间接的方式,即通过一个隐藏的B.html来实现高度自适应。

但其实整体上的思路还是比较容易理解的,就是A中含有iframe的C,但是需要一个和A同域的B在C中。 在C中需要引入iframeB, 并且在c中不断地计算自己的高度,然后设置B的src添加一个高度值,B拿到这个高度值之后,通过parent.parent来修改C,这样就可以做到完全跨域的高度自适应了。  

A.html的代码如下(其中嵌入了C,注意: AC不同域):

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8' />
    <title>A.html</title>
  </head>
  <body>
    <iframe id="ifr" src="http://snandy.jd-app.com" frameborder="0" width="100%"></iframe>
  </body>
</html>

B.html代码如下(B是嵌在C的页面中的,注意:BA同域):

注意: B是隐藏的,由于他和A同域,所以可以通过parent.parent访问到A,再改变A中iframe的高度,这是最关键的,因为AB同域,所以B可以访问到A的文档对象。

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8' />
    <title>B.html</title>
  </head>
  <body>
    <script type="text/javascript">
        window.onload = function() {
            var isSet = false
            var inteval = setInterval(function() {
                var search = location.search.replace('?', '')
                if (isSet) {
                    clearInterval(inteval)
                    return  
                }
                if (search) {
                    var height = search.split('=')[1]
                    var doc = parent.parent.document
                    var ifr = doc.getElementById('ifr')
                    ifr.style.height = height + 'px'
                    isSet = true
                }
            }, 500)
        }
    </script>
  </body>
</html>

C.html (C嵌入在A中,和A不同域,要实现C的自适应,C多高那么A的iframe就有多高,C中嵌入了B.html和D.js) 

<!doctype html>
<html>
<head>
    <title>C.html</title>
    <meta charset="utf-8">
</head>
<body>
    <h3>这是一个很长的页面,我要做跨域iframe的高度自适应</h3>
    <ul>
        <li>页面 A:http://snandy.github.io/lib/iframe/A.html</li>
        <li>页面 B:http://snandy.github.io/lib/iframe/B.html</li>
        <li>页面 C:http://snandy.jd-app.com</li>
        <li>D.js:http://snandy.github.io/lib/iframe/D.js</li>
    </ul>
    <p>A</p><p>A</p><p>A</p><p>A</p><p>A</p><p>A</p><p>A</p><p>A</p><p>A</p><p>A</p><p>A</p><p>A</p><p>A</p><p>A</p><p>A</p><p>A</p>
    <iframe id="myifr" style="display:none" src="http://snandy.github.io/lib/iframe/B.html"></iframe>
    <script type="text/javascript" src="http://snandy.github.io/lib/iframe/D.js"></script>
</body>
</html>

D.js (在页面C载入后计算其高度,然后将计算出的height赋值给C里引入的iframe(B.html)的src) 

// 计算页面的实际高度,iframe自适应会用到
function calcPageHeight(doc) {
    var cHeight = Math.max(doc.body.clientHeight, doc.documentElement.clientHeight)
    var sHeight = Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight)
    var height  = Math.max(cHeight, sHeight)
    return height
}
window.onload = function() {
    var doc = document
    var height = calcPageHeight(doc)
    var myifr = doc.getElementById('myifr')
    if (myifr) {
        myifr.src = 'http://snandy.github.io/lib/iframe/B.html?height=' + height
        // console.log(doc.documentElement.scrollHeight)     
    }
};

这里的D.js为什么要单独拿出来和AB同源呢? 不能直接把其中的代码放进去吗? 

iframe自适应高度

iframe使用场景

iframe优缺点

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>2.html</title>
    <script type="text/javascript">
        document.domain = 'jd.com'
    </script>
  </head>
  <body>
     <p>这是一个ifrmae,嵌入在3.html里 </p>
     <p>根据自身内容调整高度</p>
     <p>a</p><p>a</p><p>a</p><p>a</p><p>a</p><p>a</p><p>a</p><p>a</p>
<script>
    // 计算页面的实际高度,iframe自适应会用到
    function calcPageHeight(doc) {
        var cHeight = Math.max(doc.body.clientHeight, doc.documentElement.clientHeight)
        var sHeight = Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight)
        var height  = Math.max(cHeight, sHeight)
        return height
    }
    window.onload = function() {
        var height = calcPageHeight(document)
        parent.document.getElementById('ifr').style.height = height + 'px'     
    }
</script>
  </body>
</html>
原文地址:https://www.cnblogs.com/zhuzhenwei918/p/6759463.html