這裏再補充幾個css的知識點,下面會用到css
設置元素的最小寬度。
舉例說明,好比設置一個百分比的寬度,那麼元素的寬度的像素值是會隨着頁面大小而變化的。若是設置一個最小的像素寬度,那麼當變化到最小值以後,不會繼續變小。在下面的例子中,會出現滾動條,保證元素的寬度:html
<body> <div style="height: 80px;width: 100%;background-color: blue;min-width: 800px;"></div> <!--下面的狀況是:原本正好能放一排的,可是狂賭不夠後放不下了--> <div style="height: 80px;width: 20%;background-color: yellow;float: left"></div> <div style="height: 80px;width: 80%;background-color: red;float: right;min-width: 600px;"></div> </body>
另外,min-width 的值能夠是像素,也能夠是百分比。前端
這個屬性是爲元素添加一個圓角邊框。值能夠是像素,也能夠是百分比。
若是把值設爲50%,再保證高和寬同樣,就能作出一個圓形的邊框,放在img標籤中,就能作出一個圓形的頭像:html5
<img src="1.jpg" style="border-radius: 50%;height: 80px;width: 80px;" />
以前已經講過:hover,這裏要補充的是,不但能夠改變本身標籤的屬性,也能夠經過選擇器的語法來改變其餘標籤的屬性:python
<head> <meta charset="UTF-8"> <title>Title</title> <style> .father{ height: 100px; background-color: yellow; } .son{ height: 50%; } .father:hover{ color: red; } .father:hover .special{ background-color: blue; color: white; } </style> </head> <body> <div class="father"> <div class="son special">字體背景都變色</div> <div class="son">字體變色</div> </div> </body>
還沒完,若是咱們改變的是display屬性,那麼不須要js,僅用css也能夠實現鼠標懸停展開菜單的功能:數組
<head> <meta charset="UTF-8"> <title>Title</title> <style> .item .header{ height: 35px; background-color: blue; color: white; line-height: 35px; } .item .content{ display: none; } .item:hover .content{ display: block; } </style> </head> <body> <div class="item"> <div class="header">菜單</div> <div class="content"> <div>內容一</div> <div>內容二</div> <div>內容三</div> </div> </div> </body>
通常佈局的時候,先把頁面分紅頭部(pg-header)、中間(pg-content)、底部(pg-footer)三個部分。主要的內容周集中在中間。如今應該已經掌握了一種形式的佈局,就是商城頁面。以前沒有把佈局的問題單獨拿出來說,這節之後臺管理頁面舉例,講解佈局的問題和實現。瀏覽器
以前學習和做業都是以商城爲例子。佈局大概是這個樣子的:都是從上到下佈局,給頁面設置一個寬度,而後全部內容都是居中顯示。閉包
<head> <meta charset="UTF-8"> <title>Title</title> <style> body{ margin: 0; } .w{ width: 1000px; margin: 0 auto; } .pg-header, .pg-footer{ height: 48px; line-height: 48px; background-color: black; color: white; } .left{ float: left; } .right{ float: right; } .content1{ height: 100px; width: 160px; background-color: gold; } .content2{ width: 840px; background-color: yellow; } .goods{ height: 200px; width: 200px; border: 1px solid black; margin: 4px; } </style> </head> <body> <div class="pg-header"> <div class="w"> <div style=""> 這裏放頭部的內容 </div> </div> </div> <div class="pg-content"> <div class="w"> <div class="content1 left">這裏放中間的內容</div> <div class="content2 right"> <div class="goods left">商品信息</div> <div class="goods left">商品信息</div> <div class="goods left">商品信息</div> <div class="goods left">商品信息</div> <div class="goods left">商品信息</div> <div class="goods left">商品信息</div> <div class="goods left">商品信息</div> <div class="goods left">商品信息</div> </div> <div style="clear: both"></div> </div> </div> <div class="pg-footer"> <div class="w"> <div> 這裏放底部的內容 </div> </div> </div> </body>
常見的後臺管理頁面的佈局,一樣有頭部、中繼、底部。可是菜單通常顯示在中間的最左側(即固定在左邊),而中間的右側則是顯示的主要內容:app
<head> <meta charset="UTF-8"> <title>Title</title> <style> body{ margin: 0; } .pg-header{ height: 48px; background-color: red; } .pg-content .menu{ position: fixed; top: 48px; left: 0; bottom: 30px; width: 200px; background-color: blue; color: white; } .pg-content .content{ position: fixed; top: 48px; right: 0; bottom: 30px; left: 200px; background-color: yellow; overflow: auto; } .pg-footer{ position: fixed; height: 30px; right: 0; left: 0; bottom: 0; background-color: purple; } </style> </head> <body> <div class="pg-header"></div> <div class="pg-content"> <div class="menu">這裏是菜單</div> <div class="content"> <script> for (var i=0; i<100; i++){ document.writeln("<p>test</p>") } </script> </div> </div> <div class="pg-footer"></div> </body>
通常內容會比較多,每每一屏顯示不完。這裏就填入了不少內容,爲了能夠看到全部的內容,須要設置overflow屬性,能夠用滾輪翻頁。
這裏只是拋磚引玉,不建議這麼實現。如今來看看後面absolute的實現方法。ide
仍是上面的樣子,差很少的代碼,此次用absolute來實現。不設置relative,這裏會將元素定位在屏幕的某個位置和fixed同樣,可是滾動滾動屏幕的時候,元素會跟着上下移動。具體代碼以下:
<head> <meta charset="UTF-8"> <title>Title</title> <style> body{ margin: 0; } .pg-header{ height: 48px; background-color: red; } .pg-content .menu{ position: absolute; top: 48px; left: 0; width: 200px; background-color: blue; color: white; } .pg-content .content{ position: absolute; top: 48px; right: 0; left: 200px; background-color: yellow; /*overflow: auto;*/ /*bottom: 0;*/ } </style> </head> <body> <div class="pg-header"></div> <div class="pg-content"> <div class="menu"> <script> for (var i=0; i<10; i++){ document.writeln("<p>菜單</p>") } </script> </div> <div class="content"> <script> for (var i=0; i<100; i++){ document.writeln("<p>test</p>") } </script> </div> </div> </body>
這個樣式和上面的略有不一樣,頭部和左側會跟隨滾輪移動。這裏沒寫底部,而且暫時很差作能跟隨滾輪移動的底部。
變化新樣式:在 <style>
標籤裏,.pg-content .content
的樣式裏有兩句被註釋了,去掉註釋後,就是設置overflow。效果是和上面同樣的固定頭部和左側的樣式了。
注意:能夠再設置一個 min-width 屬性,最小寬度。在你縮小窗口的時候,當動態調整的寬度小於這個屬性時,元素的寬度就不會繼續變小了,而是會出現滾動條。這能夠有效的保證你的頁面佈局不會由於窗口大小的變化而混亂。
以前的頭部沒有任何內容,簡單的在頭部的左邊放一個LOGO,這個沒什麼難度。而後再在右邊放一個頭像,頭像使用圓形,而後鼠標懸停圖片上會展開菜單。圓形圖片和css實現鼠標懸停展開,在開頭的css補充內容裏能夠參考:
<head> <meta charset="UTF-8"> <title>Title</title> <style> body{ margin: 0; } .pg-header{ height: 48px; line-height: 48px; background-color: red; } .pg-header img{ height: 48px; } .pg-header .logo{ width: 200px; float: left; } .pg-header .user{ float: right; background-color: pink; padding: 5px; margin-right: 62px; } .pg-header .user:hover .user_list{ display: block; } .pg-header .user .profile_pic>img{ height: 40px; width: 40px; border-radius: 50%; } .pg-header .user .user_list{ z-index: 20; position: absolute; top: 48px; right: 30px; background-color: orange; width: 120px; text-align: center; display: none; } .pg-header .user .user_list>a{ display: block; } .pg-header .user .user_list>a:hover{ background-color: blue; color: white; } </style> </head> <body> <div class="pg-header"> <div class="logo"> <a style="margin: 0 auto"> <img src="1.jpg" /> </a> </div> <!--設置user的div往右飄,上面的logo要往左飄,這樣2個才能在一行--> <div class="user"> <a class="profile_pic"> <!--把頭像設置成了圓形圖片--> <img src="2.jpg"> </a> <!--user_list設置了相對定位,和下面的pg-content重疊,要設置z-index--> <div class="user_list"> <!--a標籤要設置成塊級標籤,讓它換行--> <a>個人收藏</a> <a>註銷</a> </div> </div> </div> </body>
上面是頭部的全部內容,能夠和前面的頁面內容拼接在一塊兒,就是整個頁面了。
若是要在頁面中使用圖標,推薦去 Font Awesome 找。這個是中文網: http://www.fontawesome.com.cn/
.1 先去官網下載font-awesome壓縮包
.2 解壓文件夾,把 font-awesome 的整個文件夾複製到你的項目中:
.3 在 <head>
處加載 font-awesome.min.css 以下:
<link rel="stylesheet" href="font-awesome-4.7.0/css/font-awesome.min.css">
用 <i>
標籤包裹起來,把圖標用到你網站的任何地方:
<head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="font-awesome-4.7.0/css/font-awesome.min.css"> </head> <body> <ul class="fa-ul"> <li><i class="fa-li fa fa-check-square"></i>使用列表類圖標</li> <li><i class="fa-li fa fa-check-square"></i>輕鬆的替換</li> <li><i class="fa-li fa fa-spinner fa-spin"></i>無序列表</li> <li><i class="fa-li fa fa-square"></i>中的默認圖標</li> </ul> <i class="fa fa-refresh fa-spin fa-3x fa-fw"></i> <div> <i class="fa fa-envelope-o fa-fw" aria-hidden="true"></i> <input class="form-control" type="text" placeholder="您的郵箱地址"> </div> <div> <i class="fa fa-key fa-fw" aria-hidden="true"></i> <input class="form-control" type="password" placeholder="請輸入密碼"> </div> </body>
要用圖標的話,就上網站去找,而後把代碼複製下來就好。上面還有更多使用案例。
這是另一種條件語句:
switch(n) { case 1: 執行代碼塊 1 break; case 2: 執行代碼塊 2 break; default: 都不配時才執行的代碼塊 }
break: 每一個 case 最後,請使用 break 來阻止代碼自動地向下一個 case 運行。
default:使用 default 關鍵詞來規定匹配不存在時執行的代碼。
函數就是在大括號中的代碼塊,前面使用了關鍵詞 function:
function myFunction(var1,var2) { 這裏是要執行的代碼 }
就是沒有函數名的函數,普通函數去掉函數名就是匿名函數了。只能被調用一次,好比定時器(setInterval),第一個參數是要執行的代碼,就可使用匿名函數。
function (var1,var2) { 這裏是要執行的代碼 }
自執行函數是用小括號將匿名函數包起來,而後加小括號(傳參)當即執行。由於函數無名字,實現了做用域的絕對隔離和函數名的衝突問題。基本形式以下:
(function (var1,var2) { 這裏是要執行的代碼 })(var1,var2);
普通的函數,定義完以後暫時不執行,以後經過函數名加小括號調用執行。自執行函數,定義完以後緊接着是一個小括號,立刻調用執行。
語法以下:
JSON.stringify(obj)
:序列化,將對象的狀態轉換爲字符串JSON.parse(str)
:反序列化> JSON.stringify([1,2,3,4,5]) // 序列化 < "[1,2,3,4,5]" > JSON.parse("[1,2,3,4,5]") // 反序列化 < [object Array]: [1, 2, 3, 4, 5] >
轉義urlencodeURI()
:把字符串做爲 URI 進行編碼decodeURI()
:對 encodeURI() 函數編碼過的 URI 進行解碼encodeURIComponent()
:把字符串做爲 URI 組件進行編碼decodeURIComponent()
:對 encodeURIComponent() 函數編碼的 URI 進行解碼
> url = "https://www.baidu.com/s?wd=前端" < "https://www.baidu.com/s?wd=前端" > url2 = encodeURI(url) < "https://www.baidu.com/s?wd=%E5%89%8D%E7%AB%AF" > decodeURI(url2) < "https://www.baidu.com/s?wd=前端" > url3 = encodeURIComponent(url) < "https%3A%2F%2Fwww.baidu.com%2Fs%3Fwd%3D%E5%89%8D%E7%AB%AF" > decodeURIComponent(url3) < "https://www.baidu.com/s?wd=前端"
用上面的四個方法就行了,下面兩個知道一下。escape()
:對字符串進行編碼,這樣就能夠在全部的計算機上讀取該字符串unescape()
:對經過 escape() 編碼的字符串進行解碼
注意:全部的方法不會對 ASCII 字母和數字進行編碼,也不會對這些 ASCII 標點符號進行編碼: - _ . ! ~ * ' ( )
eval() 函數可計算某個字符串,並執行其中的的 JavaScript 代碼。語法:
eval(string)
參數是字符串形式的表達式或代碼,而且能夠有返回值。
python中也是以函數做爲做用域。
在其餘語言裏,有的以代碼塊做爲做用域。其實js也能夠,經過使用let。
結合下面的第三條一塊兒理解。
這個要在函數裏套用函數的狀況下會產生這個問題
<script> var name = 'Adam'; function func() { var name = 'Bob'; function inner() { var name = 'Cara'; alert(name) } return inner } var ret = func(); ret() </script>
上面的函數,執行的結果是Cara;若是把Cara註釋掉,結果是Bob;若是把Bob再註釋掉,則結果是Adam。這就是做用域鏈。並且因爲做用域是調用以前建立的,因此和在哪裏調用這個函數沒有關係。雖然是在最外部調用的函數,可是做用域依然是定義它時的位置,即做用域是 inner 內部。
直接看例子說明:
<script> function func() { alert(name); var name = 'Adam'; } func() </script>
name的值是調用以後才賦值的,因此alert並不能取到後面的值。可是在alert以前name變量就已經建立好了,至關於在alert以前有一句 var name;
。雖然按順序看定義變量是也是在alert後面,然而其實是在執行代碼以前就完成了全部變量的聲明。一個未賦值的變量的值是 undefined ,運行的結果就是這個值。若是註釋掉賦值語句,直接取一個不存在的變量,結果會報錯(通常瀏覽器應該會捕獲這個錯誤,可是至少結果是不同的)。
js沒有類,js能夠用函數做類,定義一個類和定義一個函數同樣。
<script> // 定義類,其實這個就是構造函數 function Foo(name) { this.name = name } var obj = new Foo('Barry'); // 建立對象 var obj2 = new Foo('Oliver'); // 建立另外一個對象 alert(obj.name); // 取對象的屬性 </script>
關於this,在構造函數中的this指向新建立的對象自己。
類有屬性還有方法,屬性有了,還要方法。既然Foo是構造函數,顯然不能再Foo裏定義類的方法。這裏要引入原型,方法定義在原型裏,Foo.prototype 是 Foo 的原型:
<script> // 定義類,其實這個是構造函數 function Foo(name) { this.name = name } // 定義方法的方式,裏面是字典的形式,貌似能夠在裏面定義多個方法 Foo.prototype = { 'sayName': function () { alert(this.name) } }; var obj = new Foo('Barry'); // 建立對象 obj.sayName(); // 調用對象的方法 </script>
把這裏的概念和以前學習過的python的面向對象的概念比較一下:
作一個input的輸入框,默認在框內先填上提示內容。當用戶選擇了input框後,狀況框內的文本,讓用戶輸入。
這裏要用到2個新的事件,onfocus 和 onblur。這裏的事件不能用onclick,由於用戶有多種方式能夠選定輸入框,好比鼠標點擊,還有用Tab切換等等。要響應這類事件,使用 onfocus 。相反,若是用戶選定後離開,則觸發事件 onblur。
onfocus 事件 :在得到焦點時觸發
onblur 事件 :在失去焦點時觸發
<body> <div> <label for="keyword">關鍵字:</label> <input id="keyword" type="text" value="請輸入關鍵字" onfocus="Focus()" onblur="Blur()"> </div> <script> // 得到焦點時,確認裏面是不是默認的value;是則清空 function Focus() { var obj = document.getElementById('keyword'); if(obj.value === "請輸入關鍵字"){ obj.value = '' } } // 失去焦點時,確認內容是否爲空;是則變回默認的value function Blur() { var obj = document.getElementById('keyword'); if(obj.value.length === 0){ obj.value = "請輸入關鍵字" } } </script> </body>
另外一種實現方法:
在的html5中提供了一個新的屬性(placeholder),簡單的設置這個屬性就能完成上面的效果。前提是客戶端的瀏覽器支持html5。
<body> <div> <label for="keyword">關鍵字:</label> <input id="keyword" type="text" placeholder="請輸入關鍵字"> </div> </body>
以前已經用過經過修改標籤的 class 屬性來達到修改樣式的效果,直接添加或去除 class 來獲取或去除某個 class 的樣式。
這裏經過DOM獲取到對象後,直接修改對象的 style 屬性,更加直接。
<body> <span id="i1" style="font-size: 16px;">字體大小</span> <script> alert("點擊後修改字體大小"); obj = document.getElementById('i1'); obj.style.fontSize = '48px'; </script> </body>
這裏要注意一下style在標籤中和js中的寫法是不同的。
屬性操做,有下面這些方法:obj.setAttribute(key, value)
:設置標籤屬性obj.getAttribute(key)
:獲取標籤屬性的值obj.hasAttribute(key)
:檢查標籤是否存在該屬性obj.removeAttribute(key)
:去除標籤屬性obj.attributes()
:獲取標籤全部的屬性
方法一:經過對象來建立:document.createElement()
:建立一個標籤對象
> var tag = document.createElement('span') // 建立一個span標籤 < undefined > tag.innerText = "建立標籤" // 標籤的內容 < "建立標籤" > tag.className = 'c1' // 設置標籤的屬性 < "c1" > tag < <span class="c1">建立標籤</span>
這裏的tag是一個對象。
方法二:經過字符串來建立:
> var tag = '<span class="c1">建立標籤</span>' < undefined > tag < "<span class="c1">建立標籤</span>"
添加的時候注意內部的引號,你能夠錯開使用單引號和雙引號。另外還可使用(\"),表示字符串內的引號字符。
這裏的tag實際只是html代碼的字符串。
方法一:基於Element的操做targetElement.insertAdjacentElement(position, element);
:插入標籤對象element.insertAdjacentHTML(position, text);
:插入標籤字符串
position參數,只有4個值。beforebegin、afterbegin、beforeend、afterend。對應的位置以下所示:
<!-- beforebegin --> <p> <!-- afterbegin --> foo <!-- beforeend --> </p> <!-- afterend -->
代碼示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .c1{ color: red; } </style> </head> <body> <div id="i1"> <p>初始的內容</p> </div> <script> var tag1 = document.createElement('p'); tag1.innerText = "建立的標籤1"; tag1.className = 'c1'; var obj = document.getElementById('i1'); obj.insertAdjacentElement("beforeend", tag1); // 插入標籤對象 var tag2 = '<p class="c1">建立的標籤2</p>'; obj.insertAdjacentHTML("beforeend", tag2); // 插入標籤字符串 </script> </body> </html>
方法二:基於Node的操做
其實上面的方法應該夠用了,不過這裏還有兩個方法:var aChild = element.appendChild(aChild);
:在當前對象後面添加,和上面的 beforeend 的效果同樣。var insertedNode = parentNode.insertBefore(newNode, referenceNode);
:在父節點的下的 reference 子節點前插入。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .c1{ color: red; } </style> </head> <body> <div id="i1"> <p>初始的內容</p> </div> <script> var tag1 = document.createElement('p'); tag1.innerText = "建立的P標籤1"; tag1.className = 'c1'; var obj = document.getElementById('i1'); obj1 = obj.appendChild(tag1); var tag2 = document.createElement('div'); tag2.innerText = '建立的DIV標籤2'; tag2.setAttribute('class', 'c1'); var parentObj = document.getElementById('i1').parentNode; parentObj.insertBefore(tag2, obj); </script> </body> </html>
不必定非得要 input 來提交表單,任何標籤經過js觸發均可以提交表單。只要獲取 form 對象,調用對象的 submit() 方法便可:formObj.submit()
:提交表單
<body> <form action="https://www.baidu.com/s" id="f1"> <input type="text" name="wd" /> <input type="submit" value="搜索" /> <a onclick="submitForm()" style="border: 1px solid">點我也能提交</a> </form> <script> function submitForm() { document.getElementById('f1').submit(); } </script> </body>
在 js 中有三種消息框:警告框、確認框、提示框。
另外還有一個 console.log()
,是向控制檯輸出信息。警告框以前已經掌握了。
下面是確認框和提示框。
語法:confirm(message)
顯示一個消息的確認框。和警告框不一樣,有兩個按鈕,而且有返回值。按確認會返回true,按取消會返回false。
舉例以下,分別試試按肯定和取消的效果:
<body> <h1 id="i1">分別試試按肯定和取消</h1> <script> // 這裏順便試試自執行函數 (function () { obj = document.getElementById('i1') var r = confirm("彈出確認框"); if(r === true){ obj.innerText = "你點擊了肯定" } else { obj.innerText = "你點擊了取消" } })() </script> </body>
語法:prompt("文本","默認值")
彈出一個讓用戶輸入的對話框。第一個變量,會顯示在輸入框上面做爲提示信息。第二個變量會做爲輸入框內的默認值事先填寫好。
<body> <script> (function () { var name = prompt("請輸入你的名字", "張三"); if(name.length > 0){ document.write("<p>你好,"+ name) } })() </script> </body>
如今誰還用彈出框作交互呢,用 input 應該根據友好吧。
location.href
:設置或返回完整的 URL。
示例,先用瀏覽器隨便打開一個頁面,進入控制檯測試:
> location.href // 返回當前的url < "about:blank" > location.href = "http://www.51cto.com" // 設置url,頁面會跳轉
location.reload()
:從新加載
location對象是包含有關當前 URL 的信息,還有更多屬性和方法,這裏只分別舉例了兩個經常使用的。
用兩種定時器,一種是循環執行的定時器,一種是隻執行一次的定時器:setInterval(code,millisec)
:按照指定的週期(以毫秒計)來調用函數或計算表達式。clearInterval(t)
,取消這個定時器。setTimeout(code,millisec)
:在指定的毫秒數後調用函數或計算表達式。clearTimeout(t)
,取消這個定時器
上面兩個方法都有返回值(假設是t),後面的方法就是用於取消這個定時器的,具體看下面的例子:
<body> <h1>定時器測試<span id="i1"></span></h1> <script> // 啓動一個定時器,每秒刷新顯示內容 var count = 0; t = setInterval(function () { count ++; document.getElementById('i1').innerText = count }, 1000); // 設置另外一個定時器,5秒後清除前面的定時器,並彈框 setTimeout("clearInterval(t); alert('結束')", 5000) </script> </body>
timeout 定時器的應用場景,好比當你點擊某個按鈕後,會顯示一條提示信息,可是信息不用永久顯示在哪裏,通過一段時間後該條信息會自動消失。這時就要用到這種只執行一次的定時器了:
<body> <div id="i1">點擊下面的按鈕</div> <div> <input type="button" value="開始" onclick="start()"> <input type="button" value="取消" onclick="stop()"> </div> <script> var t; // 這裏先把t聲明爲全局變量,下面的兩個function裏都是全局的t // 點擊按鈕後顯示一條提示消息,2秒後變回原來的信息 function start() { obj = document.getElementById('i1'); obj.innerText = "你剛點了開始(2秒後消息消失)"; t = setTimeout(function () { obj.innerText = "點擊下面的按鈕" }, 2000) } // 點了取消按鈕後,清除了計時器,文字就不會變回去了 function stop() { clearTimeout(t); } </script> </body>
這裏的事件都以onclick事件舉例,事件綁定的方法有下面幾種
在標籤內寫onclick事件。以前都是用這個方法綁定事件的,簡單,直觀,可是LOW。
在JS寫onclick=function(){}函數。推薦用這種方法綁定事件。結構更加清晰,讓js代碼從html標籤中剝離出來。
<body> <p> 在標籤內寫onclick事件 <input type="button" onclick="func()" value="點我1"> </p> <p> 在JS寫onclick=function(){}函數 <input type="button" value="點我2" id="i2"> </p> <script> function func() { alert("點我1") } document.getElementById('i2').onclick = function () { alert("點我2") } </script> </body>
從上面的例子中並看不出有什麼優點,假如咱們有不少標籤要綁定同一個事件,那麼只要在js裏寫一個for循環就能一次所有完成綁定了:
<body> <input type='button' value='0'/> <input type='button' value='1'/> <script> list_btn = document.getElementsByTagName('input'); // 給全部的button都綁定下面的事件 for(var i=0; i<list_btn.length; i++){ list_btn[i].onclick = function () { // alert(list_btn[i].value); // 這句是錯的 // alert(i); // 上面的問題,看看這個i的值 alert(this.value); // 這裏的this指的是調用這個函數的對象,其實仍是上面的list_btn[i],可是不能那麼寫 } } </script> </body>
上面的例子中,若是使用第一個alert的寫法,會報錯。得用最後的寫法,用this來指代當前的對象(即標籤)。這裏產生問題的緣由是js做用域的問題。
在上面的例子中,若是咱們放開第二個alert語句查看i的值,就會發現,始終是2。由於這裏i不是這個函數內的局部變量,而是在函數外部一直在變的,最終的值是2。因此上面的數組要取下標2天然是取不到的。解決方法就是用this,這裏誰調用這個函數,這個this就指向誰。
既然是做用域的問題,那麼不用this,經過閉包來限制做用域同樣也是能夠實現的。
<body> <input type='button' value='0'/> <input type='button' value='1'/> <script> list_btn = document.getElementsByTagName('input'); // 給全部的button都綁定下面的事件 for(var i=0; i<list_btn.length; i++){ // 外面再套一層function,作成一個閉包 // 把i的值傳遞給arg,這裏arg的做用域是這裏閉包內 (function (arg) { list_btn[i].onclick = function () { alert(list_btn[arg].value); // 如今應該對了 // alert(arg); // 看看這裏變量的值 } })(i) } </script> </body>
確定仍是用this簡單,通常都用this,這裏就展開解釋一下做用域的問題。
上面的方法將事件綁定寫在js中的方法基本已經夠用了,仍有不足。若是須要爲一個標籤綁定兩個onclick事件,以前的方法顯然都沒法實現。就要用到 addEventListener ,下面只是簡單的講一下實現上面這種需求的實現方法,更深就算了。target.addEventListener(type, listener, useCapture);
:將 type 的事件類型註冊到 target 對象上。
type :表示監聽事件類型的字符串。這裏 click 表示按下並釋聽任意鼠標按鍵(沒有 onclick)。
listener :在這裏寫上要觸發的函數
useCapture :布爾值,默認false。兩個元素都對同一個事件註冊了一個處理函數時有兩種不一樣的事件傳播方式,事件冒泡(false)和事件捕獲(true)。
先不考慮第三個參數,點擊按鈕後要觸發了兩個事件,分別修改 i1 和 i2 的樣式:
<body> <h1 id="i1">Test1</h1> <h1 id="i2">Test2</h1> <input id="btn" type="button" value="改變字體顏色"> <script> obj1 = document.getElementById('i1'); obj2 = document.getElementById('i2'); btn = document.getElementById('btn'); btn.addEventListener('click', function () { obj1.style.color = 'red' }); btn.addEventListener('click', function () { obj2.style.color = 'blue' }); </script>
下面是有元素嵌套的狀況,這時候第三個參數就有區別了。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> #main{ background-color: blue; width: 500px; height: 400px; } #content{ background-color: red; width: 300px; height: 200px; } </style> </head> <body> <h1 id="i1">看個人顏色</h1> <div id="main"> <div id="content"></div> </div> <script> var farther = document.getElementById('main'); var son = document.getElementById('content'); var str = document.getElementById('i1'); farther.addEventListener('click', function () { str.style.color = 'blue' }, true); // 就是這裏的參數會影響運行的結果,改爲false試試 son.addEventListener('click', function () { str.style.color = 'red' }); </script> </body> </html>
當有元素重疊的時候,同時出發一個事件,每一個元素的事件執行會有前後順序。默認是false,冒泡,先執行內層元素的事件,而後向外傳播。上面的例子中設置了true,捕獲,先執行外層元素的事件,而後往內傳播。當點擊重疊區域的時候,每一個事件都響應並執行了,最後執行的是內層的事件,因此最後變成了內層事件設置的顏色。
這周的內容並無做業,要等學了下週的jQuery一塊兒搞個做業了。