最近在開發一個react項目,項目是用create-react-app腳手架建立的,當我在個人項目的菜單欄中添加了一個打開一個外鏈的a標籤時,我收到了一個來自create-react-app的警告信息,信息內容以下
<img alt="opener警告" src="http://198.252.107.180/~gongm...; width="100%"/>html
意思就是說「在沒有rel="noopener noreferrer"屬性的a標籤中使用target="_blank"存在必定的風險」react
這個提示瞬間把我吸引了,之前關於a標籤收到的提示都是沒有設置alt屬性啊什麼的,可是也只是提示我說爲了顯示的友好什麼的,此次居然提示我有風險,面對這種問題,必須一探究竟啊。git
查閱了一些資料獲得了以下關於a標籤一個介紹github
當一個外部連接使用了target=_blank的方式,這個外部連接會打開一個新的瀏覽器tab。此時,新頁面會打開,而且和原始頁面佔用同一個進程。這也意味着,若是這個新頁面有任何性能上的問題,好比有一個很高的加載時間,這也將會影響到原始頁面的表現。若是你打開的是一個同域的頁面,那麼你將能夠在新頁面訪問到原始頁面的全部內容,包括document對象(window.opener.document)。若是你打開的是一個跨域的頁面,你雖然沒法訪問到document,可是你依然能夠訪問到location對象。
不看不知道一看嚇一跳有木有。主要是兩個點是我之前從未在乎的跨域
第一個問題不用我說都知道是很是須要注意的,新的頁面中的全部行爲都會間接影響到原始頁面的性能。瀏覽器
這裏主要研究第二個問題。爲此,我作了小小的實驗。app
上圖解釋:oop
上面兩個頁面的代碼分別以下:性能
opener-test.html測試
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <a target="_blank" href="test-opener-2.html">打開一個新頁面</a> </body> </html>
opener-test-2.html
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <h1>我是新打開的頁面</h1> <button type="button" id="btn">告訴打開個人那個頁面,我喜歡林志玲</button> <script> document.getElementById('btn').addEventListener('click', function() { var _opener = window.opener; var p = _opener.document.createElement('p'); p.innerHTML = "我喜歡林志玲"; p.style.color = "#f33"; _opener.document.body.appendChild(p); setTimeout(function() { _opener.location.href = "//www.baidu.com"; }, 5000) }); </script> </body> </html>
新的頁面不只往原始頁面添加了一段話,並且還讓他離開了原來的頁面。
注:在上面的例子中,兩個頁面位於同一個域下面,若是兩個頁面位於不一樣的域,那上面的第一個效果就是不行的,由於不一樣域的狀況下,新頁面拿不到opener對象的document,可是location對象是能夠拿到的,因此第二個效果任然有效。
怎麼禁止上面的行爲呢?按照create-react-app的提示信息,給鏈接加上rel屬性,以下:
<a rel="noopener noreferrer" target="_blank" href="https://marvengong.github.io/fastmock-docs/book/">
上面的rel屬性值多了一個noreferrer它的做用和noopener是同樣的,只是適用於低版本的瀏覽器。
這樣處理後,新打開的頁面的window對象上就沒有opener和referrer對象了。