zoukankan      html  css  js  c++  java
  • 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>
  • 相关阅读:
    vue.js---利用vue cli脚手架工具+webpack创建项目遇到的坑
    List<KeyValuePair<TKey,TValue>> 与 Dictionary<TKey,TValue> 不同
    StackExchange.Redis 官方文档(一) Basics
    离线安装chrome插件
    Cocoapods的安装与使用
    多线程
    作业二:个人编程项目——编写一个能自动生成小学四则运算题目的程序
    初学者如何在博客园发布博客
    作业一:建立博客、自我介绍、速读教材、学习进度总结
    计科131同学们的博客
  • 原文地址:https://www.cnblogs.com/zhuzhenwei918/p/6759463.html
Copyright © 2011-2022 走看看