Python自動化開發學習16-前端內容綜合進階
這裏再補充幾個css的知識點,下面會用到
最小寬度-min-width
設置元素的最小寬度。
舉例說明,比如設置一個百分比的寬度,那麽元素的寬度的像素值是會隨著頁面大小而變化的。如果設置一個最小的像素寬度,那麽當變化到最小值之後,不會繼續變小。在下面的例子中,會出現滾動條,保證元素的寬度:
<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 的值可以是像素,也可以是百分比。
圓形邊框-border-radius
這個屬性是為元素添加一個圓角邊框。值可以是像素,也可以是百分比。
如果把值設為50%,再保證高和寬一樣,就能做出一個圓形的邊框,放在img標簽中,就能做出一個圓形的頭像:
<img src="1.jpg" style="border-radius: 50%;height: 80px;width: 80px;" />
:hover進階用法
之前已經講過:hover,這裏要補充的是,不但可以改變自己標簽的屬性,也可以通過選擇器的語法來改變其他標簽的屬性:
<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>
布局-fixed
常見的後臺管理頁面的布局,同樣有頭部、中繼、底部。但是菜單一般顯示在中間的最左側(即固定在左邊),而中間的右側則是顯示的主要內容:
<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的實現方法。
布局-absolute
還是上面的樣子,差不多的代碼,這次用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
如果要在頁面中使用圖標,推薦去 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>
要用圖標的話,就上網站去找,然後把代碼復制下來就好。上面還有更多使用案例。
JavaScript 進階
switch 語句
這是另外一種條件語句:
switch(n)
{
case 1:
執行代碼塊 1
break;
case 2:
執行代碼塊 2
break;
default:
都不配時才執行的代碼塊
}
break: 每個 case 最後,請使用 break 來阻止代碼自動地向下一個 case 運行。
default:使用 default 關鍵詞來規定匹配不存在時執行的代碼。
函數(function)
普通函數
函數就是在大括號中的代碼塊,前面使用了關鍵詞 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-執行字符串
eval() 函數可計算某個字符串,並執行其中的的 JavaScript 代碼。語法:
eval(string)
參數是字符串形式的表達式或代碼,並且可以有返回值。
作用域
一、js默認是以函數作為作用域的(不考慮let)。
python中也是以函數作為作用域。
在其他語言裏,有的以代碼塊作為作用域。其實js也可以,通過使用let。
二、js函數的作用域,在函數未被調用之前就已經創建。
結合下面的第三條一起理解。
三、函數的作用域存在作用域鏈,並且也是在被調用之前創建。
這個要在函數裏套用函數的情況下會產生這個問題
<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 內部。
四、js函數內的變量提前聲明
直接看例子說明:
<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理解
把這裏的概念和之前學習過的python的面向對象的概念比較一下:
- 函數名就是類名
- new 類名() ,創建對象,就是實例化。
- 函數本身就是構造函數,函數中的this,就是構造函數中的self
- 類名.prototype 是原型,可以理解為就是類。裏面定義的函數就是類裏定義的方法。
DOM 和 JavaScript 的補充內容
input示例
做一個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中的寫法是不一樣的。
- 樣式名稱的分隔符,中橫杠(-)去掉了,在js裏是小駝峰的形式
- 賦值不再用冒號(:),在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>
JavaScript 消息框
在 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 對象
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,捕獲,先執行外層元素的事件,然後往內傳播。當點擊重疊區域的時候,每個事件都響應並執行了,最後執行的是內層的事件,所以最後變成了內層事件設置的顏色。
Python自動化開發學習16-前端內容綜合進階