最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 你不了解的iframe

    正文概述 掘金(manas)   2021-08-10   509

    简介

    在开发的过程中,即使在现代浏览器的中,有时还是会遇到使用iframe的时候,虽然iframe在性能和安全方面,有很多诟病,但是它还是有一些用途,能够解决一些棘手的问题。本身将会列举几个用于。

    iframe是什么呢?

    iframe全称inline frame。顾名思义,嵌入在一个HTML上下文中的窗口。尽管是嵌入到另一个文档中的上下文,但iframe仍然拥有属于自己的滚动条。

    iframe的优缺点

    优点

    1. 作为一个完全独立的窗口去运行另一个页面,而不用去担心污染。
    2. 解决加载缓慢的第三方内容如图标和广告等的加载问题
    3. 并行的加载资源文件

    缺点

    1. 占用同源连接数,对于每个浏览器,都会去控制并发的同源的连接数。比如说chrome的连接数是8,firfox的连接数6。所以如果iframe的请求与页面的请求是同源的,那么就会阻塞页面的请求。
    2. iframe无法使用浏览器的前进和后退键
    3. 对SEO不友好
    4. 阻塞onload的加载

    iframe的简单使用

    <iframe id="inlineFrameExample"
        
        width="300"
        height="200"
        src="https://www.openstreetmap.org/export/embed.html?bbox=-0.004017949104309083%2C51.47612752641776%2C0.00030577182769775396%2C51.478569861898606&layer=mapnik">
    </iframe>
    

    你可能不知道用途

    不使用websocket进行轮询

    websocket无法使用的时候,作为长轮询功能的解决方案。主要用于实现ie8、9这种早期浏览器的轮询功能。一开始在谷歌中有使用过Comet:基于 HTTP 长连接的“服务器推”技术

    1. 创建服务端,新建一个接口

    /* GET users listing. */
    router.get('/users', function(req, res, next) {
      res.send('respond with a resource');
    });
    

    2. 编写客户端js

    <div class="iframe-content" />
    <script>
        // 创建一个iframe并将它隐藏
        const iframeEle = document.createElement('iframe');
        iframeEle.style = 'display: none;';
        iframeEle.name = 'poll';
        iframeEle.src="http://localhost:3000/users";
        // 监听load事件,请求完成后将会运行load事件
        iframeEle.onload = function() {
            var iframeLoc = iframeEle.contentWindow.location;
            var result = iframeEle.contentDocument;
            // 这里将会拿到响应的结果
            var text = result.getElementsByTagName('body')[0].textContent;
            console.log(text)
            // 设置定时器,实现轮询功能
            setTimeout(function() {
                iframeLoc.reload(); 
            }, 3000);
        }
        var iframeContent = document.getElementsByClassName('iframe-content')[0];
        iframeContent.appendChild(iframeEle);
    </script>
    

    你不了解的iframe

    不使用formData上传文件

    当我们不能使用formData上传文件时,我们可以使用iframe进行页面无刷新的上传文件。方法其实很简单,就是使用iframe代替当前页面上传,只需要将定义好的form标签的target赋值为iframename属性。

    1. 页面代码
        <form id="submit-form" name="submit-form" target="submit-iframe"  enctype="multipart/form-data" action="/upload" method="POST">
            <input type="file" name="files">
            <button type="submit" id="submit-btn">上传</button>
        </form>
        需要注意到。iframe的name和form的target属性是一致的
        <iframe style="display: none;" id="submit-iframe" name="submit-iframe"></iframe>
        <script>
            const iframeEle = document.getElementById('submit-iframe');
            // 上传完成后,可以在iframe中拿到响应的结果
            iframeEle.onload= function() {
                var iframeLoc = iframeEle.contentWindow.location;
                var resultWrapper = iframeEle.contentDocument;
                var result = resultWrapper.getElementsByTagName('body')[0].textContent;
                console.log(result);
            }
        </script>
    
    1. 上传接口
    var express = require('express');
    var multer = require('multer');
    var router = express.Router();
    
    let storage=multer.diskStorage({
        destination:(req,file,cb)=>{
            cb(null,'upload/');
        },
        filename:(req,file,cb)=>{
            cb(null,file.originalname);
        }
    })
    
    var upload = multer({
      storage
    })
    
    router.post('/upload', upload.single('files'),function(req, res, next) {
      res.send("上传完成");
    })
    

    iframe跨域解决跨域请求

    1. 创建主页面

    主页面中包含了2个iframe,一个用于请求不同域的接口fetchFrame。一个用于轮询监听前者的location变化observeFrame。且主页面包含一个回调方法用于供observeFrame调用。

        <div class="iframe-content">
            <div>主页面</div>
            <!-- 同域 -->
            <iframe src="http://hsa.guahao-test.com:3000/fetch.html" name="fetch" id="fetch"></iframe>
            <!-- 不同域 -->
            <iframe src="http://tcmedev.udplat.com:8080/observe.html" name="inner" id="inner"></iframe>
        </div>
        <script>
            // 主页面用于iframe的回调函数
            window.message = function(str) {
                console.log(str);
            }
        </script>
    

    2. 编写fetchFrame的代码

    fetchFrame的页面中,可以看到代码使用setTimeout进行模拟异步请求,在回调函数中会将结果存放进window.name中,并改变location的指向。需要注意的是,我们使用的是window.name去处理iframe的数据传递。因为window.name在改变窗口地址的情况下不会改变数据且它具有2M的空间大小。但是在不同域的情况下,window.name无法被访问到,所以在赋值完成后会改变iframe的地址。

    setTimeout(() => {
        // 存放数据
        window.name = new Date();
        // 改成location,使得与主页面同源
        window.location = 'http://tcmedev.udplat.com:8080/index3.html'
    }, 3000);
    

    3. 编写observeFrame的代码

    observeFrame中,创建了一个定时器去轮询fetchFramewindow对象,在不同域的情况下,访问异步的iframe会抛出错误。所以代码中使用try-catch进行包裹,当fetchFramelocation改为同域的时候,就可以正常的访问fetchFramewindow.name,并调用父级的回调函数。

    <script>
        var fetchFrame = window.parent.document.getElementById('fetch');
        if(fetchFrame) {
            const interval = setInterval(() => {
                const fetchFrameWindow = fetchFrame.contentWindow;
                const hostname = fetchFrameWindow.location;
                try {
                    // 这时,请求已经完成
                    if(fetchFrameWindow.location.hostname !== hostname) {
                        clearInterval(interval);
                        if(window.top && window.top.message) {
                            // 调用主页面声明的回调函数
                            window.top.message(fetchFrameWindow.name)
                        }
                    }
                } catch (error) {
                    // 捕获跨域异常
                    console.log("还在请求当中")
                }
            }, 1000);
        }
    </script>
    

    你不了解的iframe

    浏览器端实现utf8和gbk编码互转

    在开发的过程中,有时难免会遇到编码问题。比如说服务端需要提交的参数是gbk,又或者我们需要使用到gbk的字符串。对于这些场景,使用JavaScript的encodeURI或者encodeURIComponent等浏览器的全局api都无法完成。但可以使用form标签的accept-charset,以下为文档上的描述

    举一个简单的例子

    <form action="form_action.asp" accept-charset="gbk">
      <input  type="text" name="test" value="这里是一串字符串" />
      <input type="submit" value="Submit" />
    </form>
    

    尝试提交后,得到的结果是 你不了解的iframe 我们可以看到请求的query上test后面跟着一串(unable to decode value), 这是因为gbk编码无法解析。

    我们已经有了生成gbk编码的字符串的方法了。但是还是没法拿到。这个时候就可以用前面使用到的form标签的target。

    你不了解的iframe 使用target=“framename”就可以提交字符串到对应的iframe,而在iframe中我们就能拿到编码完成的字符串了。

    <form target="encode" accept-charset="gbk" >
      <input  type="text" name="test" value="这里是一串字符串" />
      <input type="submit" value="Submit" />
    </form>
    <iframe name="encode" style="display:none" src='about:blank' id="encode"></iframe>
    <script>
    // 上面代码中创建了一个iframe标签和form标签,form标签会把表单提交到encode的iframe
    var frame = document.getElementById("encode");
    
    // 定义了一个回调函数
    window.callback = function(result) {
        console.log(result);
    }
    // 从iframe的onload事件得到结果
    frame.onload = function() {
         //打印frame的location.search可以得到 ?test=%D5%E2%C0%EF%CA%C7%D2%BB%B4%AE%D7%D6%B7%FB%B4%AE
        result = frame.contentWindow.location.search.split("=")[1]
        frame.contentWindow.parent.callback(result)
    }
    </script>
    

    你不了解的iframe


    起源地下载网 » 你不了解的iframe

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元