iframe的用法

iframe原本的用法在現在看來是不合時宜的,問題太多了,不一一列舉,但是它的其他功能卻是不錯的黑魔法,這里列舉一些,想到了再更新:

用來實現長連接,在websocket不可用的時候作為一種替代,最開始由google發明。Comet:基于 HTTP 長連接的“服務器推”技術

跨域通信。JavaScript跨域總結與解決辦法,類似的還有瀏覽器多頁面通信,比如音樂播放器,用戶如果打開了多個tab頁,應該只有一個在播放。

歷史記錄管理,解決ajax化網站響應瀏覽器前進后退按鈕的方案,在html5的history api不可用時作為一種替代。

純前端的utf8和gbk編碼互轉。比如在utf8頁面需要生成一個gbk的encodeURIComponent字符串,可以通過頁面加載一個gbk的iframe,然后主頁面與子頁面通信的方式實現轉換,這樣就不用在頁面上插入一個非常巨大的編碼映射表文件了,其中子頁面內容:

window.encoding=function(str){//利用a元素的href屬性來encodevara=document.createElement("a");a.href="/?q="+str;varurl=a.href;//這里讀取的時候會自動編碼a.href="/?q=";returnurl.replace(a.href,"");};

把這個iframe部署到父頁面的同源服務上,就能在父頁面直接調用iframe中的encoding接口了。

評論里有提到,用iframe實現無刷新文件上傳,在FormData不可用時作為替代方案

在移動端用于從網頁調起客戶端應用(此方法在iphone上并不安全,慎用!具體風險看這里iOS URL Scheme 劫持)。比如想在網頁中調起支付寶,我們可以創建一個iframe,src為:

alipayqr://platformapi/startapp?saId=10000007&clientVersion=3.7.0.0718&qrcode={支付二維碼掃描的url}

瀏覽器接收到這個url請求發現未知協議,會交給系統處理,系統就能調起支付寶客戶端了。我們還能趁機檢查一下用戶是否安裝客戶端:給iframe設置一個3-5秒的css3的transition過渡動畫,然后監聽動畫完成事件,如果用戶安裝了客戶端,那么系統會調起,并將瀏覽器轉入后臺運行,進入后臺的瀏覽器一般不會再執行css動畫,這樣,我們就能通過判斷css動畫執行的時長是否超過預設來判斷用戶是否安裝某個客戶端了:

/*** 調起客戶端* @param url {String}* @param onSuccess {Function}* @param onFail {Function}*/module.exports=function(url,onSuccess,onFail){// 記錄起始時間varlast=Date.now();// 創建一個iframevarifr=document.createElement('IFRAME');ifr.src=url;// 飄出屏幕外ifr.style.position='absolute';ifr.style.left='-1000px';ifr.style.top='-1000px';ifr.style.width='1px';ifr.style.height='1px';// 設置一個4秒的動畫用于檢查客戶端是否被調起ifr.style.webkitTransition='all 4s';document.body.appendChild(ifr);setTimeout(function(){// 監聽動畫完成時間ifr.addEventListener('webkitTransitionEnd',function(){document.body.removeChild(ifr);if(Date.now()-last<6000){// 如果動畫執行時間在預設范圍內,就認為沒有調起客戶端if(typeofonFail==='function'){onFail();}}elseif(typeofonSuccess==='function'){// 動畫執行超過預設范圍,認為調起成功onSuccess();}},false);// 啟動動畫ifr.style.left='-10px';},0);};

創建一個全新的獨立的宿主環境。經@EtherDream大神提醒,iframe還可以用于創建新的宿主環境,用于隔離或者訪問原始接口及對象,比如有些前端安全的防范會覆蓋一些原生的方法防止惡意調用,那我們就能通過創建一個iframe,然后從iframe中取回原始對象和方法來破解這種防范。類似的還有@賀師俊曾經提到的javascript裸對象創建中的一種方法:如何創建一個JavaScript裸對象,一般所見即所得編輯器也是由iframe創建的,@Dion的回答有提到

IE6下用于遮罩select。經@yaniv提醒想起來的。曾經在ie6時代,想搞一個模態窗口,如果窗口疊加在select元素上面,是遮不住select的,為了解決這個問題,可以通過在模態窗口元素下面墊一個iframe來實現遮罩,好坑爹的ie6,還我青春韶華~~

使用 iframe 是不是一個好的用法(good practice),不能一概而論,但是可以肯定是,現在的大部分網站避免采用這種方式的。

比較早期的網站使用 iframe,主要是用于導航欄(navigator)。為什么?

因為一個網站很多頁面的導航欄部分是相同的,在避免切換頁面的時候重復下載,將導航欄和正文分開在 iframe 中,是一個方便的做法。

同時帶來的不利是,默認情況下,使用了 iframe 的網站的 URL 不會隨著頁面的變化而變化。

這就意味著一旦刷新,網站可能又回到首頁。

那么現在的網站是如何解決不同頁面使用相同的 navigator 而避免重復編碼呢?

不同后臺技術都有自己的方法,比如 ASP 有 SSI,PHP 有 require、require_once 或 include 函數,JSP 也有 include 指令。

iframe 一直是瀏覽器標準規范之一,只有很早期的瀏覽器不支持 iframe,現在幾乎已絕跡。

所以從兼容性上來說,iframe 是沒問題的。

那么現在什么時候會用到 iframe 呢?

因為 iframe 的頁面和父頁面(parent)是分開的,所以它意味著,這是一個獨立的區域,不受 parent 的 CSS 或者全局的 JavaScript 的影響。

典型的,比如所見即所得的網頁編輯器(WYSIWYG Online HTML Editor),因為它們需要 reset 自己的 CSS 到自己的標準,而不被 parent CSS 的 override。

說到上面一點了,順便說一下,知乎的這個編輯器不是用 iframe,它使用了一種叫 contentEditable 的屬性,用來啟用頁面元素的編輯,在早期版本 IE 下不支持的。

正是因為剛剛提到的 iframe 等于新建了一個全新的,不受 parent 影響的頁面上下文,所以在一定程度上,類似于沙箱隔離(sandbox)。

除此之外,如果有可以不用 iframe 來解決的問題,還是避免使用 iframe。

替代方案一般就是動態語言的 include 機制、ajax 動態填充內容,以及以后會普及的 contentEditable

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • <a name='html'>HTML</a> Doctype作用?標準模式與兼容模式各有什么區別? (1)、<...
    clark124閱讀 3,556評論 1 19
  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實際上跨域的范圍絕對不止那么狹隘。具體概念如下:只要協議...
    w_zhuan閱讀 532評論 0 0
  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實際上跨域的范圍絕對不止那么狹隘。具體概念如下:只要協議...
    他在發呆閱讀 829評論 0 0
  • 2011年的考驗總結,那是一場戰爭,人這一生中很少有一次為一件事那么拼,考研算一件。 今天粘貼出了當年的部分文字,...
    妞妞喜歡扭一扭閱讀 245評論 0 1
  • 作者:王之樂自明星塑造者 來源:原創 很少有人知道群的運營目的是什么,因為群比內容還難量化質量的好壞,當我們要判斷...
    之樂日記閱讀 475評論 0 0