Created By JishuBao on 2019-04-12 12:38:22
Recently revised in 2019-04-12 17:38:22javascript
歡迎你們來到技術寶的掘金世界,您的star是我寫文章最大的動力!GitHub地址
感受已經好久沒寫掘金了,多是由於閱讀量沒多少把,沒有動力寫,可是我想了想寫博客主要仍是記錄本身在工做中遇到的問題,主要仍是以本身學習爲主,因此仍是寫上一寫吧哈哈哈。
html
就在今天上午遇到了一個問題,封裝一個很簡單的彈框,須要作到哪一個頁面須要這個彈框,直接引入這個Js文件,執行操做就能夠彈出彈框,點擊確認彈框消失,由於前面工做中都是之前端框架vue、react爲主,已經習慣了那種組件化的開發模式,而且寫組件只須要import一下仍是很方便的,可是引入js文件的這種我說實話仍是第一次碰見,畢竟咱們公司尚未作到真正的先後端分離,頁面仍是jsp頁面,因此我真的也是很心累的。確實難到了我,因此準備寫下來本身寫好的代碼~。萬一哪天忘記了還能夠再調用這樣子,哈哈。大概圖是這樣,真的很簡單~前端
以前看了好多代碼,都有用到這種函數的寫法,可是都沒認真的去想爲何會這樣寫,今天開始想學習下jquery的源碼,發現jquery也是使用這種方式,用(function(window, undefined){})(window)包裹內部代碼,因而進一步的去學習了下。 要理解當即執行函數(function(){})(),先了解些函數的基本概念(函數聲明、函數表達式、匿名函數)。vue
使用function聲明函數,並指定函數名java
function Fn(){
//coding...
}
複製代碼
使用function聲明函數,但未指定函數名,將匿名函數賦予一個變量。node
var Fn=function(){
//coding...
}
複製代碼
使用function關鍵字聲明函數,但未指定函數名。匿名函數屬於函數表達式,匿名函數有不少做用,賦予一個變量則建立函數,賦予一個事件則成爲事件處理程序或建立閉包等。react
function(){
//coding
}
複製代碼
setFn()
function setFn(){
//coding
}
//正常,函數聲明可提早調用
setFn()
var setFn=function(){
//coding
}
//報錯 setFn未保存對函數的引用,函數調用需放在函數表達式後面
複製代碼
var setFn=function(){
console.log('setFn')
}()
//解析至此 可直接執行調用,即無需再調用,打印出setFn
複製代碼
從上面咱們能夠看到 函數表達式寫法後面加括號能夠無需調用直接執行jquery
var setFn=function(){
console.log('setFn')
}()
//解析至此 可直接執行調用,即無需再調用,打印出setFn
複製代碼
簡化就是var setFn=function(){}()
,而咱們的當即執行函數是(function(){})()
,當即執行函數(function(){})()能夠看出很像函數表達式的調用,但欸什麼要加括號呢?若是不加括號:git
function(){
//coding
}()
//報錯,函數須要函數名
複製代碼
雖然匿名函數屬於函數表達式,但未進行賦值,因此javascript解析時將開頭的function看成函數聲明,故報錯須要函數名es6
當即執行函數裏面的函數必須是函數表達式,因此由var setFn = function() {}()能夠理解爲在匿名函數前加了 = 運算符後,將函數聲明轉化爲函數表達式,因此拿!,+,-,()...等運算符來測試下是否如此。
!function(){
console.log(1)
}()
// 1
+function(){
console.log(2)
}()
// 2
-function(){
console.log(3)
}()
// 3
(function(){
console.log(4)
})()
// 4
複製代碼
因而可知,加運算符確實可將函數聲明轉化爲函數表達式,而之因此使用括號,是由於括號相對其餘運算符會更安全,能夠減小沒必要要的麻煩。
當即執行函數與正常函數傳參形式是一致的。
(function(a, b){
console.log(a + b);
})(1, 2)
// 3
複製代碼
(function(){}())這樣寫的好處是在內部定義的變量不會跟外部的變量有衝突,達到保護內部變量的做用。
首先新建mymodal.js文件
(function(window){
// 使用構造函數方法 聲明一個Modal對象
var Modal=function(ele){
this.$el=ele;
this.init();
}
// 在Modal的原型上實現close,open,init方法,實現方法的複用
Modal.prototype.close=function(){
this.$el.style.display='none';
}
Modal.prototype.open=function(){
this.$el.style.display='block';
}
Modal.prototype.init=function(){
var self=this;
// 綁定關閉按鈕點擊事件處理函數,檢索全部 帶 .close類名 的按鈕
if(this.$el.addEventListener){
this.$el.addEventListener('click',function(e){
e.preventDefault();
var target=e.target;
var classNames=target.className.split(' ');
if(classNames.indexOf('close')!==-1){
self.close();
}
},false);
}else if(this.$el.attachEvent){
this.$el.attachEvent('onclick',function(e){
e=e||window.event;
if(e.preventDefault){
e.preventDefault();
}else{
e.returnValue=false;
}
var target=e.target||e.srcElement;
var classNames=target.className.split(' ');
if(classNames.indexOf('close')!==-1){
self.close();
}
});
}
}
})(window)
複製代碼
新建mymodal.html頁面
<!doctype html>
<html>
<head>
<meta charset="utf-8"></meta>
<title>測試彈框demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
</head>
<body>
<div class="container">
<div class="wrapbutton">
<div class="button" id="button">點擊出現彈框按鈕</div>
<div class="my-modal" id="my-modal" style="display:none;">
<div class="my-modal-dialog">
<div class="my-modal-content">今日22:00-15:00都屬於系統維護階段</div>
<div class="my-modal-controller">
<div class='my-btn-ok close'>肯定</div>
</div>
</div>
</div>
</div>
<script src="mymodal.js"></script>
<script type="text/javascript">
document.getElementById('button').onclick=function(){
var mymodal=new Modal(document.getElementById('my-modal'));
mymodal.open();
}
</script>
</div>
</body>
<style>
*{
margin:0;
padding:0;
box-sizing:border-box;
}
html,body{
width:100%;
height:100%;
}
.container{
width:100%;
height:100%;
display:table;
}
.container .wrapbutton{
display:table-cell;
vertical-align:middle;
text-align:center;
}
.container .button{
width:250px;
height:100px;
background-color:#1890ff;
font-size:22px;
border-radius:10px;
display:inline-block;
line-height: 95px;
box-shadow: 4px 3px 5px -1px #1890ff;
color:white;
font-weight:500;
}
.my-modal{
position:fixed;
top:0;
bottom:0;
left:0;
right:0;
background-color:rgba(0,0,0,.3);
transform:all .5s
z-index:10
}
.my-modal-dialog{
width: 60%;
min-height: 20%;
border: 1px solid rgb(153,153,153);
border-radius: 12px;
position: absolute;
background-color: #fff;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
.my-modal-content{
padding: 20px 15px;
line-height: 1.5em;
}
.my-modal-controller{
border-top: 0.5px solid rgba(0,0,0,.3);
font-size: 20px;
height: 50px;
display: table;
position: absolute;
width: 100%;
bottom: 0;
}
.my-btn-ok{
text-align: center;
display: table-cell;
vertical-align: middle;
}
</style>
</html>
複製代碼
瀏覽器打開mymodal便可看到以下效果:
點擊按鈕出現modal框,點擊肯定modal消失
若是這個彈框只有一個頁面用到卻是很好弄,可是公司要求這個彈框須要被不少頁面引用,若是都加一塊div的話不免會出現不少冗雜的代碼,也不利於後期維護,可是公司用的是傳統的jsp、html不能使用我熟悉的es6語法import 心很累,因此我瞄準了iframe,說實話我面試的時候每天背關於iframe的面試題,即便我根本不知道iframe是什麼東西(笑哭),如今就來使用Iframe優化咱們的項目吧!
<!doctype html>
<html>
<head>
<meta charset="utf-8"></meta>
<title>彈框組件</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
</head>
<body>
<div class="my-modal" id="my-modal" style="display:none;">
<div class="my-modal-dialog">
<div class="my-modal-content">今日22:00-15:00都屬於系統維護階段</div>
<div class="my-modal-controller">
<div class='my-btn-ok close'>肯定</div>
</div>
</div>
</div>
</body>
<style>
.my-modal{
position:fixed;
top:0;
bottom:0;
left:0;
right:0;
background-color:rgba(0,0,0,.3);
z-index:10
}
.my-modal-dialog{
width: 60%;
min-height: 20%;
border: 1px solid rgb(153,153,153);
border-radius: 12px;
position: absolute;
background-color: #fff;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
.my-modal-content{
padding: 20px 15px;
line-height: 1.5em;
}
.my-modal-controller{
border-top: 0.5px solid rgba(0,0,0,.3);
font-size: 20px;
height: 50px;
display: table;
position: absolute;
width: 100%;
bottom: 0;
}
.my-btn-ok{
text-align: center;
display: table-cell;
vertical-align: middle;
}
</style>
</html>
複製代碼
<!doctype html>
<html>
<head>
<meta charset="utf-8"></meta>
<title>測試彈框demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
</head>
<body>
<div class="container">
<div class="wrapbutton">
<div class="button" id="button">點擊出現彈框按鈕</div>
</div>
<script src="mymodal.js"></script>
<script type="text/javascript">
document.getElementById('button').onclick=function(){
var mymodal=new Modal(document.getElementById('my-modal'));
mymodal.open();
}
</script>
</div>
</body>
<style>
*{
margin:0;
padding:0;
box-sizing:border-box;
}
html,body{
width:100%;
height:100%;
}
.container{
width:100%;
height:100%;
display:table;
}
.container .wrapbutton{
display:table-cell;
vertical-align:middle;
text-align:center;
}
.container .button{
width:250px;
height:100px;
background-color:#1890ff;
font-size:22px;
border-radius:10px;
display:inline-block;
line-height: 95px;
box-shadow: 4px 3px 5px -1px #1890ff;
color:white;
font-weight:500;
}
</style>
</html>
複製代碼
在頁面引入iframe標籤,接下來的要點就是獲取Iframe裏面的元素了,那獲取iframe的元素如何獲取呢,讓咱們來看下。
<iframe src="modalComponent" name="modalComponent" id="modalComponent"
width="0" height="0" frameborder="0" scrolling="no" ></iframe>
複製代碼
經過百度 咱們發現有如下幾種方式
var iframe = document.getElementById("iframe1");
var iwindow = iframe.contentWindow;
var idoc = iwindow.document;
console.log("window",iwindow);//獲取iframe的window對象
console.log("document",idoc); //獲取iframe的document
console.log("html",idoc.documentElement);//獲取iframe的html
console.log("head",idoc.head); //獲取head
console.log("body",idoc.body); //獲取body
複製代碼
另外更簡單的方式是,結合Name屬性,經過window提供的frames獲取.
console.log(window.frames['ifr1'].window);
console.log(document.getElementById("ifr1").contentWindow);
複製代碼
其實window.frames['ifr1']返回的就是window對象,即
window.frames['ifr1']===window
複製代碼
當咱們準備用console.log(window.frames['modalComponent'].document.getElementById('my-modal'));
獲取彈框的Id時,卻出現了這個錯誤!!!
iframe就是一個隔離沙盒,至關於咱們在一個頁面內能夠操控不少個標籤頁同樣。若是踩坑的童鞋應該知道,iframe的解決跨域也是頗有套套的。
首先咱們須要明確什麼是跨域。
瀏覽器判斷你跨沒跨域,主要根據兩個點。 一個是你網頁的協議(protocol),一個就是你的host是否相同,即,就是url的首部:
window.location.protocol +window.location.host
複製代碼
須要強調的是,url首部必須同樣,好比:二級域名或者IP地址,都算是跨域.
//域名和域名對應ip, 跨域
http://www.a.com/a.js
http://70.32.92.74/b.js
//統一域名,不一樣二級域名。 跨域
http://www.a.com/a.js
http://a.com/b.js
複製代碼
對於第二種狀況,iframe能夠解決 如:
www.foo.com/a.html 和 script.foo.com/b.html 兩個文件中分別加上document.domain = ‘foo.com’,指定相同的主域,而後,兩個文檔就能夠進行交互。
//b.html是以iframe的形式嵌套在a.html中
//www.foo.com上的a.html
document.domain = 'foo.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.foo.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
var doc = ifr.contentDocument || ifr.contentWindow.document;
// 在這裏操縱b.html
alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};
//script.foo.com上的b.html
document.domain = 'foo.com';
複製代碼
默認狀況下document.domain 是指window.location.hostname. 你能夠手動更改,可是最多隻能設置爲主域名。 一般,主域名就是指不帶www的hostname, 好比: foo.com , baidu.com 。 若是,帶上www或者其餘的前綴,就是二級域名或者多級域名。經過上述設置,相同的domain以後,就能夠進行同域的相關操做。 另外還可使用iframe和location.hash,不過因爲技術out了,這裏就不作介紹了。
說明:本人興致滿滿的百度寫了好長時間的文章,發現拆分的話使用代碼實現不了 可是因爲百度了一些時間 也就不刪除了 小夥伴只須要看前2章就好了!!