天天看點

Javascript筆記大全03BOMPC端網頁特效

BOM

簡介

BOM(Browser Object Model)即浏覽器對象模型,它提供了獨立于内容而與浏覽器視窗進行互動的對象,其核心對象使window

差別

DOM

  1. 文檔對象模型
  2. DOM就是把【文檔】當做是一個【對象】來看待
  3. DOM的頂級對象是document
  4. DOM主要學習的是操作頁面元素
  5. DOM是W3C标準規範

BOM

  1. 浏覽器對象模型
  2. 把【浏覽器】當做是一個【對象】來看待
  3. BOM的頂級對象是window
  4. BOM學習的是浏覽器視窗互動的一些對象
  5. BOM是浏覽器廠商在各自浏覽器上定義的,相容性較差

BOM比DOM更大,它包含DOM

調整視窗大小事件

window.onresize = function() {}
window.addEventListener('resize',function() {});
           

window.onresize是調整視窗大小加載事件,當觸發時就調用的處理函數

注意:

  1. 隻要視窗大小發生變化,就會觸發這個事件
  2. 經常利用這個事件完成響應式布局,window.innerWidth 目前螢幕的寬度
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			div {
				width: 200px;
				height: 200px;
				background-color: pink;
			}
		</style>
	</head>
	<body>
		<script type="text/javascript">
			window.addEventListener('load',function() {
				// 粉色盒子随着視窗大小而顯示或者隐藏
				// 擷取div
				var div = document.querySelector('div');
				window.addEventListener('resize',function() {
					console.log(window.innerWidth);
					
					console.log('變化了');
					if (window.innerWidth <= 800) {
						div.style.display = 'none';
					} else {
						div.style.display = 'block';
					}
				})
			})
		</script>
		<div></div>
	</body>
</html>
           

定時器

window對象給我們提供了2個非常好用的方法-定時器

  1. setTimeout()
  2. setInterval()

setTimeout() 定時器

setTimeout() 方法用于設定一個定時器,該定時器在定時器到期後執行調用函數

注意:

  1. window可以省略
  2. 這個調用函數可以直接寫函數,或者寫函數名或者采取字元串 ‘函數名()’ 三種方式。第三種不推薦
  3. 延遲的毫秒數省略預設是0,如果寫,必須是毫秒
  4. 因為定時器可能有很多,是以我們經常給定時器指派一個辨別符

setTimeout() 這個調用函數也稱為回調函數 callback,普通函數是按照代碼順序直接調用,而這個函數,需要等待時間,時間到了才去調用這個函數,是以稱為回調函數。

簡單了解:回調,就是回頭調用的意思。上一件事幹完,再回頭調用這個函數

案例

5秒之後自動關閉的廣告

  1. 核心思路:5秒之後,就把廣告隐藏起來
  2. 用定時器setTimeout
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<img src="./img/廣告.jpg" class="ad" width="500px">
		<script type="text/javascript">
			var ad = document.querySelector('.ad');
			setTimeout(function() {
				ad.style.display = 'none';
			}, 5000);
		</script>
	</body>
</html>
           

停止setTimeout() 定時器

window.clearTimeout (timeoutID)
           

clearTimeout() 方法取消了先前通過調用setTimeout()建立的定時器

注意:

  1. window可以省略
  2. 裡面的參數就是定時器的辨別符
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<!-- 點選按鈕後不會輸出'爆炸了',否則5秒後輸出'爆炸了' -->
		<button>點選停止定時器</button>
		<script type="text/javascript">
			var btn = document.querySelector('button');
			var timer = setTimeout(function() {
				console.log('爆炸了');
			}, 5000);
			btn.addEventListener('click',function() {
				clearTimeout(timer);
			})
		</script>
	</body>
</html>
           

setInterval() 定時器

setInterval() 方法重複調用一個函數,每隔這個時間,就去調用一次回調函數

注意:

  1. window可以省略
  2. 這個調用函數可以直接寫函數,或者寫函數名或者采取字元串 ‘函數名()’ 三種形式
  3. 間隔的毫秒數省略預設是0,如果寫,必須是毫秒,表示每間隔多少毫秒就自動調用這個函數
  4. 因為定時器可能有很多,是以我們經常給定時器指派一個辨別符
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script type="text/javascript">
			// 文法規範: window.setInterval(調用函數,延時時間);
			setInterval(function() {
				console.log('連續中出');
			}, 1000);
		</script>
	</body>
</html>
           

案例

秒殺倒計時

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			div {
				text-align: center;
				margin-top: 100px;
			}
			span {
				background-color: black;
				width: 50px;
				height: 50px;
				text-align: center;
				line-height: 50px;
				color: #fff;
				font-size: 20px;
				margin:50px 0;
				padding: 20px 20px;
			}
		</style>
	</head>
	<body>
		<div>
			<span class="hour">1</span>
			<span class="minute">2</span>
			<span class="second">3</span>
		</div>
		<script type="text/javascript">
			// 1.擷取元素
			var hour = document.querySelector('.hour'); // 小時的黑色盒子
			var minute = document.querySelector('.minute'); // 分鐘的黑色盒子
			var second = document.querySelector('.second'); // 秒數的黑色盒子
			
			var inputTime = +new Date('2021-8-2 19:00:00'); // 傳回的是使用者輸入時間總的毫秒數
			countDown(); // 先調用一次這個函數,防止重新整理頁面有空白
			
			// 開啟定時器
			setInterval(countDown, 1000);
			
			function countDown() {
				var nowTime = +new Date(); // 傳回的是目前時間總的毫秒數
				
				var times = (inputTime - nowTime) / 1000; // times是剩餘時間總的毫秒數
				var h = parseInt(times / 60 / 60); // 時
				h = h < 10 ? '0' + h : h;
				hour.innerHTML = h; // 把剩餘的小時 給 小時的黑色盒子
				
				var m = parseInt(times / 60 % 60); // 分
				m = m < 10 ? '0' + m : m;
				minute.innerHTML = m;
				
				var s = parseInt(times % 60); // 目前的秒
				s = s < 10 ? '0' + s : s;
				second.innerHTML = s;
			}
		</script>
	</body>
</html>
           
Javascript筆記大全03BOMPC端網頁特效

差別

  1. setTimeout 延時時間到了,就去調用這個回調函數,隻調用一次就結束了這個定時器
  2. setInterval 每隔一個這個延時時間,就去調用這個回調函數,會調用很多次,重複調用這個函數

停止setInterval() 定時器

window.clearInterval(intervalID);
           

clearInterval() 方法取消了先前通過調用setInterval()建立的定時器

注意:

  1. window可以省略
  2. 裡面的參數就是定時器的辨別符
<body>
	<button class="begin">開啟定時器</button>
	<button class="stop">停止定時器</button>
	<script type="text/javascript">
		var begin = document.querySelector('.begin');
		var stop = document.querySelector('.stop');
		var timer = null; // 全局變量 null是一個空對象
		begin.addEventListener('click',function() {
			timer = setInterval(function() {
				console.log('你好啊');
			}, 1000);
		})
		stop.addEventListener('click',function() {
			clearInterval(timer);
		})
	</script>
</body>
           

案例

發送短信

<body>
	手機号碼: <input type="number"> <button>發送</button>
	<script type="text/javascript">
		// 按鈕點選之後,會禁用disabled為true
		// 同時按鈕裡面的内容會變化,注意button裡面的内容通過innerHTML修改
		// 裡面秒數是有變化的,是以需要用到定時器
		// 定義一個變量,在定時器裡面,不斷遞減
		// 如果變量為0 說明到了時間,我們需要停止定時器,并且複原按鈕初始狀态
		var btn = document.querySelector('button');
		var time = 3; // 定義剩下的秒數
		btn.addEventListener('click',function() {
			btn.disabled = true;
			var timer = setInterval(function() {
				if (time == 0) {
					// 清除定時器和複原按鈕
					clearInterval(timer);
					btn.disabled = false;
					btn.innerHTML = '發送';
					time = 3; // 這個3需要從新開始
				} else {
					btn.innerHTML = '還剩下' + time + '秒';
					time--;
				}
			}, 1000);
		})
	</script>
</body>
           

同步和異步

Javascript的一大特點就是單線程,就是說,同一個時間隻能做一件事。單線程就意味着,所有任務需要排隊,前一個任務結束,才會執行後一個任務。這樣會導緻:如果JS執行時間過長,會造成頁面的渲染不連貫。

同步

前一個任務結束後再執行後一個任務,程式的執行順序與任務的排列順序是一緻的、同步的。

比如做飯的同步做法:燒水煮飯,等水開了,再去切菜、炒菜。

異步

在做一件事情時,因為這件事情會花費很長時間,在做這件事的同時,還可以去處理其他事情。

比如做飯的異步做法:在燒水的同時,利用這10分鐘,去切菜、炒菜。

同步和異步的本質差別:這條流水線上各個流程的執行順序不同

以下代碼執行的結果是什麼?

console.log(1);
setTimeout(function() {
    console.log(3);
}, 0);
console.log(2);
           

結果:1 2 3

執行機制

  1. 先執行 執行棧 中的同步任務
  2. 異步任務(回調函數)放入任務隊列中
  3. 一旦執行棧中的所有同步任務執行完畢,系統就會按次序讀取任務隊列中的異步任務,于是被讀取的異步任務結束等待狀态,進入執行棧,開始執行。
Javascript筆記大全03BOMPC端網頁特效

location 對象

URL的一般文法格式為:

protocol://host[:post]/path/[?query]#fragment
http://www.itcast.cn/index.html?name=andy&age=18#link
           
組成 說明
protocol 通信協定 常用的http,ftp,maito等
host 主機(域名)www.itheima.com
port 端口号 可選,省略時使用方案的預設端口 如http的預設端口為80
path 路徑 由 0 或多個’/'符号隔開的字元串,一般用來表示主機上的一個目錄或檔案位址
query 參數 以鍵值對的形式,通過&符号分隔開來
fragment 片段 #後面内容 常見于連結、錨點

location對象的屬性

location對象屬性 傳回值
location.href 擷取或者設定整個URL
location.host 傳回主機(域名)www.itheima.com
location.port 傳回端口号 如果未寫傳回空字元串
location.pathname 傳回路徑
location.search 傳回參數
location.hash 傳回片段 #後面内容 常見于連結、錨點

重點記住:href 和 search

<body>
	<button>點選</button>
	<div></div>
	<script type="text/javascript">
		var btn = document.querySelector('button');
		var div = document.querySelector('div');
		// 點選跳轉
		btn.addEventListener('click',function() {
			location.href = 'http://www.baidu.com';
		})
		// n秒後跳轉
		var timer = 5;
		setInterval(function() {
			if (timer == 0) {
				location.href = 'http://www.baidu.com';
			} else {
				div.innerHTML = '将在'+ timer +'秒鐘之後跳轉';
				timer--;
			}
		}, 1000);
	</script>
</body>
           

案例

  1. 第一個登入頁面,裡面有送出表單,action送出到index.html頁面
  2. 第二個頁面,可以使用第一個頁面的參數,這樣實作了一個資料不同頁面之間的傳遞效果
  3. 第二個頁面之是以可以使用第一個頁面的資料,是利用了URL裡面的location.search參數
  4. 在第二個頁面中,需要把這個參數提取
  5. 第一步去掉? 利用substr
  6. 第二步利用=号分割鍵和值 split(’=’)

login.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<form action="index.html">
			使用者名:<input type="text" name="uname"/>
			<input type="submit" value="登入"/>
		</form>
		<script type="text/javascript">
			console.log(location.search);
			// 1.先去掉? substr('起始位置','截取幾個字元');
			var params = location.search.substr(1);
			console.log(params);
			// 2.利用=把字元串分割為數組 split('=');
			var arr = params.split('=');
			console.log(arr);
		</script>
	</body>
</html>
           

index.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div></div>
		<script type="text/javascript">
			console.log(location.search);
			// 1.先去掉? substr('起始位置','截取幾個字元');
			var params = location.search.substr(1);
			console.log(params);
			// 2.利用=把字元串分割為數組 split('=');
			var arr = params.split('=');
			console.log(arr);
			var div = document.querySelector('div');
			// 3.把資料寫入div中
			div.innerHTML = arr[1] + '歡迎您';
		</script>
	</body>
</html>
           

location對象的方法

location對象方法 傳回值
location.assign() 跟href一樣,可以跳轉頁面(也稱為重定向頁面)
location.replace() 替換目前頁面,因為不記錄曆史,是以不能後退頁面
location.reload() 重新加載頁面,相對于重新整理按鈕或者f5 如果參數為true 強制重新整理 Ctrl + f5

navigator對象

navigator對象包含有關浏覽器的資訊,它有很多屬性,最常用的時userAgent,該屬性可以傳回客戶機發送伺服器的user-agent頭部的值

判斷使用者哪個終端打開頁面,實作跳轉

if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|blackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
	window.location.href = ''; // 手機
} else {
	window.location.href = ''; // 電腦
}
           

history對象

window對象給我們提供了一個history對象,與浏覽器曆史記錄進行互動。

history對象方法 作用
back() 可以後退功能
forward() 前進功能
go(參數) 前進後退功能 參數如果是1前進1個頁面,如果是-1後退一個頁面

history對象一般在實際開發中比較少用,但是會在一些OA辦公系統中見到。

PC端網頁特效

元素偏移量offset系列

offset翻譯過來就是偏移量,使用offset系列相關屬性可以動态的得到該元素的位置(偏移)、大小等

  1. 獲得元素距離帶有定位父元素的位置
  2. 獲得元素自身的大小(寬度高度)
  3. 注意:傳回的數值都不帶機關

offset系列常用屬性:

offset系列屬性 作用
element.offsetParent 傳回作為該元素帶有定位的父級元素 如果父級都沒有定位則傳回body
element.offsetTop 傳回元素相對帶有定位父元素上方的偏移
element.offsetLeft 傳回元素相對帶有定位父元素左邊框的偏移
element.offsetWidth 傳回自身包括padding、邊框、内容區的寬度,傳回數值不帶機關
element.offsetHeight 傳回自身包括padding、邊框、内容區的高度,傳回數值不帶機關
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			* {
				padding: 0;
				margin: 0;
			}
			.father {
				position: relative;
				width: 200px;
				height: 200px;
				background-color: pink;
				margin: 100px;
			}
			.son {
				width: 100px;
				height: 100px;
				background-color: plum;
				margin-left: 45px;
			}
		</style>
	</head>
	<body>
		<div class="father">
			<div class="son"></div>
		</div>
		<script type="text/javascript">
			// offset系列
			var father = document.querySelector('.father');
			var son = document.querySelector('.son');
			// 可以得到元素的偏移 位置 傳回的不帶機關的數值
			console.log(father.offsetTop); // 100
			console.log(father.offsetLeft); // 100
			// 它以帶有定位的父親為準 如果沒有父親或者父親沒有定位 則以body為準
			console.log(son.offsetLeft); // 45
		</script>
	</body>
</html>
           
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			* {
				padding: 0;
				margin: 0;
			}
			.w {
				width: 200px;
				height: 200px;
				background-color: skyblue;
				margin: 0 auto 200px;
				padding: 10px;
			}
		</style>
	</head>
	<body>
		<div class="w"></div>
		<script type="text/javascript">
			// offset系列
			var w = document.querySelector('.w');
			// 可以得到元素的大小、寬度、高度,是包含padding + border + width
			console.log(w.offsetWidth); // 220
			console.log(w.offsetHeight); // 220
		</script>
	</body>
</html>
           

offset與style的差別

offset

  1. 可以得到任意樣式表中的樣式值
  2. 獲得的數值沒有機關
  3. 包含padding + border + width
  4. offsetWidth等屬性是隻讀屬性,隻能擷取不能指派
  5. 是以,想要擷取元素大小位置,用offset更合适

style

  1. 隻能得到行内樣式表中的樣式值
  2. style.width獲得的是帶有機關的字元串
  3. style.width獲得不包括padding和border的值
  4. style.width是可讀寫屬性,可以擷取也可以指派
  5. 是以,想要給元素更改值,則需要用style改變
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			.box {
				width: 500px;
				height: 500px;
				background-color: pink;
				margin: 0 auto;
			}
		</style>
	</head>
	<body>
		<div class="box"></div>
		<script type="text/javascript">
			// 在盒子内點選,想要得到滑鼠距離盒子左右的距離
			// 首先得到滑鼠在頁面中的坐标(e.pageX,e.pageY)
			// 其次得到盒子在頁面中的距離(box.offsetLeft,box.offsetTop)
			// 用滑鼠距離頁面的坐标減去盒子在頁面中的距離,得到滑鼠在盒子内的坐标
			var box = document.querySelector('.box');
			box.addEventListener('click',function(e) {
				// console.log(e.pageX);
				// console.log(e.pageY);
				// console.log(box.offsetLeft);
				var x = e.pageX - this.offsetLeft;
				var y = e.pageY - this.offsetTop;
				this.innerHTML = 'x坐标是' + x + 'y坐标是' + y;
			})
		</script>
	</body>
</html>
           

元素可視區client系列

通過client系列的相關屬性可以動态的得到該元素的邊框大小、元素大小等

client系列屬性 作用
element.clientTop 傳回元素上邊框的大小
element.clientLeft 傳回元素左邊框的大小
element.clientWidth 傳回自身包括padding、内容區的寬度,不含邊框,傳回數值不帶機關
element.clientHeight 傳回自身包括padding、内容區的高度,不含邊框,傳回數值不帶機關
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			div {
				width: 200px;
				height: 200px;
				background-color: pink;
				border: 10px solid red;
			}
		</style>
	</head>
	<body>
		<div></div>
		<script type="text/javascript">
			// client寬度 和offsetWidth最大的差別就是 不包含邊框
			var div = document.querySelector('div');
			console.log(div.clientWidth); // 200
		</script>
	</body>
</html>
           

立即執行函數

主要作用:建立一個獨立的作用域

<body>
	<script type="text/javascript">		
        function fn() {
			console.log(1);
		}
		fn();			// 1.立即執行函數:不需要調用,立馬能夠自己執行的函數
		// 2. 寫法 也可以傳遞參數進來
		// (function () {})()  或者  (function(){}())
		(function(a,b) {
			console.log(a + b); // 3
			var num = 10;
		})(1,2); // 第二個小括号可以看做是調用函數
		
		(function sum(a,b) {
			console.log(a + b); // 5
			var num = 10; // 局部變量
		}(2,3));
		// 3.立即執行函數最大的作用就是:獨立建立一個作用域,裡面所有的變量都是局部變量 不會有命名沖突的情況
	</script>
</body>
           

元素滾動scroll系列屬性

使用scroll系列的相關屬性可以動态的得到該元素的大小、滾動距離等

scroll系列屬性 作用
element.scrollTop 傳回被卷去的上側距離,傳回數值不帶機關
element.scrollLeft 傳回被卷去的左側距離,傳回數值不帶機關
element.scrollWidth 傳回自身實際的寬度,不含邊框,傳回數值不帶機關
element.scrollHeight 傳回自身實際的高度,不含邊框,傳回數值不帶機關
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			div {
				width: 200px;
				height: 200px;
				background-color: pink;
				border: 10px solid red;
				padding: 10px;
				overflow: auto;
			}
		</style>
	</head>
	<body>
		<div>
			 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
			 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
			 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容 我是内容
		</div>
		<script type="text/javascript">
			// scroll系列
			var div = document.querySelector('div');
			console.log(div.scrollHeight); // 這裡是440,數值随着内容的增加而增大
			console.log(div.clientHeight); // 220
		</script>
	</body>
</html>
           

案例

  1. 原先側邊欄是絕對定位
  2. 當頁面滾動到一定位置,側邊欄改為固定定位
  3. 頁面繼續滾動,會讓傳回頂部顯示出來
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			.slider-bar {
				position: absolute;
				left: 50%;
				top: 300px;
				margin-left: 600px;
				width: 45px;
				height: 130px;
				background-color: pink;
			}
			
			.w {
				width: 1200px;
				margin: 10px auto;
			}
			
			.header {
				height: 150px;
				background-color: purple;
			}
			
			.banner {
				height: 250px;
				background-color: skyblue;
			}
			
			.main {
				height: 1000px;
				background-color: yellowgreen;
			}
			
			span {
				display: none;
				position: absolute;
					bottom: 0;
			}
		</style>
	</head>
	<body>
		<div class="slider-bar">
			<span class="goBack">傳回頂部</span>
		</div>
		<div class="header w">頭部區域</div>
		<div class="banner w">banner區域</div>
		<div class="main w">主體部分</div>
		<script type="text/javascript">
			// 擷取元素
			var sliderbar = document.querySelector('.slider-bar');
			var banner = document.querySelector('.banner');
			// banner.offsetTop就是被卷去頭部的大小一定要寫到滾動的外面
			var bannerTop = banner.offsetTop;
			// 當側邊欄固定定位之後應該變化的數值
			var sliderbarTop = sliderbar.offsetTop - bannerTop;
			// 擷取main主體元素
			var main = document.querySelector('.main');
			var goBack = document.querySelector('.goBack');
			var mainTop = main.offsetTop;
			
			// 頁面滾動事件 scroll
			document.addEventListener('scroll',function() {
				// window.pageYoffset 頁面被卷去的頭部
				// 當頁面被卷去的頭部大于等于172 此時 側邊欄就要改為固定定位
				if (window.pageYOffset >= 172) {
					sliderbar.style.position = 'fixed';
					sliderbar.style.top = sliderbarTop + 'px';
				} else {
					sliderbar.style.position = 'absolute';
					sliderbar.style.top = '300px';
				}
				// 當頁面滾動到main盒子,就顯示goback子產品
				if (window.pageYOffset >= mainTop) {
					goBack.style.display = 'block';
				} else {
					goBack.style.display = 'none';
				}
			})
		</script>
	</body>
</html>
           

頁面被卷去的頭部相容性解決方案

頁面被卷去的頭部,有相容性問題,是以被卷去的頭部通常有如下幾種寫法:

  1. 聲明了DTD,使用document.documentElement.scrollTop
  2. 聲明了DTD,使用document.body.scrollTop
  3. 新方法window.pageYoffset 和 window.pageXoffset,IE9開始支援
function getScroll() {
    return {
        left:window.pageXoffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0,
        top:window.pageYoffset || document.documentElement.scrollTop || document.body.scrollTop || 0
    };
}
// 使用的時候
getScroll().left
           

三大系列總結

三大系列大小對比 作用
element.offsetWidth 傳回自身包括padding、邊框、内容區的寬度,傳回數值不帶機關
element.clientWidth 傳回自身包括padding、内容區的寬度,不含邊框,傳回數值不帶機關
element.scrollWidth 傳回自身實際的寬度,不含邊框,傳回數值不帶機關

主要用法

  1. offset系列經常用于獲得元素位置 offsetLeft offsetTop
  2. client系列經常用于擷取元素大小 clientWidth clientHeight
  3. scroll系列經常用于擷取滾動距離 scrollTop scrollLeft
  4. 注意頁面滾動的距離通過 window.pageXoffset 獲得

動畫函數封裝

核心原理:通過定時器setinterval()不斷移動盒子位置

步驟:

  1. 獲得盒子目前位置
  2. 讓盒子在目前位置加上1個移動距離
  3. 利用定時器不斷重複這個操作
  4. 加一個結束定時器的條件
  5. 注意此元素需要添加定位,才能使用element.style.left
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			div {
				position: absolute;
				left: 0;
				width: 100px;
				height: 100px;
				background-color: pink;
			}
		</style>
	</head>
	<body>
		<div></div>
		<script type="text/javascript">
			var div = document.querySelector('div');
			
			var timer = setInterval(function() {
				if(div.offsetLeft >= 400) {
					// 停止動畫 本質是停止定時器
					clearInterval(timer);
				}
				div.style.left = div.offsetLeft + 1 + 'px';
			}, 30);
		</script>
	</body>
</html>
           

動畫函數給不同元素記錄不同定時器

如果多個元素都使用這個動畫函數,每次都要var聲明定時器。可以給不同元素使用不同的定時器(自己專門用自己的定時器)

核心原理:利用js是一門動态語言,可以很友善的給目前對象添加屬性

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			div {
				position: absolute;
				left: 0;
				width: 100px;
				height: 100px;
				background-color: pink;
			}
			
			span {
				position: absolute;
				left: 0;
				top: 200px;
				display: block;
				width: 150px;
				height: 150px;
				background-color: purple;
			}
		</style>
	</head>
	<body>
		<button>點選阿波才走</button>
		<div></div>
		<span>阿波</span>
		<script type="text/javascript">
			// 簡單動畫函數封裝obj目标對象 target 目标位置
			// 給不同的元素指定了不同的定時器
			function animate(obj,target) {
				// 當不斷點選按鈕,這個元素的速度會越來越快,因為開啟了太多的定時器
				// 解決方案是:讓我們元素隻有一個定時器執行
				// 先清除以前的定時器,隻保留目前的一個定時器執行
				clearInterval(obj.timer);
				obj.timer = setInterval(function() {
					if(obj.offsetLeft >= target) {
						// 停止動畫 本質是停止定時器
						clearInterval(timer);
					}
					obj.style.left = obj.offsetLeft + 1 + 'px';
				}, 30);
			}
			
			var div = document.querySelector('div');
			var span = document.querySelector('span');
			var btn = document.querySelector('button');
			// 調用函數
			animate(div,300);
			
			btn.addEventListener('click',function() {
				animate(span,200);
			})
		</script>
	</body>
</html>
           

緩動效果

緩動動畫就是讓元素運動速度有所變化,最常見的是讓速度慢慢停下來

思路:

  1. 讓盒子每次移動的距離慢慢變小,速度就會慢慢落下來
  2. 核心算法:(目标值-現在的位置)/ 10 做為每次移動的距離步長
  3. 停止的條件是:讓目前盒子位置等于目标位置就停止定時器
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			span {
				position: absolute;
				left: 0;
				top: 200px;
				display: block;
				width: 150px;
				height: 150px;
				background-color: purple;
			}
		</style>
	</head>
	<body>
		<button class="btn500">點選阿波到500</button>
		<button class="btn800">點選阿波到800</button>
		<span>阿波</span>
		<script type="text/javascript">
			// 簡單動畫函數封裝obj目标對象 target 目标位置
			function animate(obj,target) {
				// 先清除以前的定時器,隻保留目前的一個定時器執行
				clearInterval(obj.timer);
				obj.timer = setInterval(function() {
					// 步長值寫道定時器的裡面
					var step = (target - obj.offsetLeft) / 10;
					// 把步長值改為整數 不要出現小數的問題
					step = step > 0 ? Math.ceil(step) : Math.floor(step);
					if(obj.offsetLeft == target) {
						// 停止動畫 本質是停止定時器
						clearInterval(obj.timer);
					}
					// 把每次加1這個步長值改為一個慢慢變小的值,步長公式:(目标值-現在的位置)/ 10
					obj.style.left = obj.offsetLeft + step + 'px';
				}, 15);
			}
			
			var span = document.querySelector('span');
			var btn500 = document.querySelector('.btn500');
			var btn800 = document.querySelector('.btn800');
			// 調用函數
			btn500.addEventListener('click',function() {
				animate(span,500);
			})
			btn800.addEventListener('click',function() {
				animate(span,800);
			})
			// 勻速動畫 就是 盒子是目前的位置 + 固定的值 10
			// 緩動動畫 就是 盒子目前的位置 + 變化的值(目标值 - 現在的位置)/ 10)
		</script>
	</body>
</html>
           

動畫函數添加回調函數

回調函數:函數可以作為一個參數。将這個函數作為參數傳到另一個函數裡面,當那個函數執行完之後,再執行傳進去的這個函數,這個過程叫回調。

回調函數寫的位置:定時器結束的位置

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			span {
				position: absolute;
				left: 0;
				top: 200px;
				display: block;
				width: 150px;
				height: 150px;
				background-color: purple;
			}
		</style>
	</head>
	<body>
		<button class="btn500">點選阿波到500</button>
		<button class="btn800">點選阿波到800</button>
		<span>阿波</span>
		<script type="text/javascript">
			// 簡單動畫函數封裝obj目标對象 target 目标位置
			function animate(obj,target,callback) {
				// 先清除以前的定時器,隻保留目前的一個定時器執行
				clearInterval(obj.timer);
				obj.timer = setInterval(function() {
					// 步長值寫道定時器的裡面
					var step = (target - obj.offsetLeft) / 10;
					// 把步長值改為整數 不要出現小數的問題
					step = step > 0 ? Math.ceil(step) : Math.floor(step);
					if(obj.offsetLeft == target) {
						// 停止動畫 本質是停止定時器
						clearInterval(obj.timer);
						// 回調函數寫到定時器結束裡面
						if (callback) {
							// 調用函數
							callback();
						}
					}
					// 把每次加1這個步長值改為一個慢慢變小的值,步長公式:(目标值-現在的位置)/ 10
					obj.style.left = obj.offsetLeft + step + 'px';
				}, 15);
			}
			
			var span = document.querySelector('span');
			var btn500 = document.querySelector('.btn500');
			var btn800 = document.querySelector('.btn800');
			// 調用函數
			btn500.addEventListener('click',function() {
				animate(span,500);
			})
			btn800.addEventListener('click',function() {
				// 使盒子變紅色的函數
				animate(span,800,function() {
					// alert('你好嗎');
					span.style.backgroundColor = 'red';
				});
			})
			// 勻速動畫 就是 盒子是目前的位置 + 固定的值 10
			// 緩動動畫 就是 盒子目前的位置 + 變化的值(目标值 - 現在的位置)/ 10)
		</script>
	</body>
</html>
           

輪播圖

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>最簡單的輪播效果</title>
	<link rel="stylesheet" type="text/css" href="css/index.css"/>
	<script type="text/javascript" src="js/index.js"></script>
</head>
	<body>
		<div class="focus">
			<!-- 左側按鈕 -->
			<a href="javascript:;" class="arrow-l">&lt;</a>
			<!-- 右側按鈕 -->
			<a href="javascript:;" class="arrow-r">&gt;</a>
			<!-- 核心的滾動區域 -->
			<ul>
				<li><a href="#"><img src="img/破敗大事件.jpg" ></a></li>
				<li><a href="#"><img src="img/靈能特工.jpg" ></a></li>
				<li><a href="#"><img src="img/烈陽皎月.jpg" ></a></li>
				<li><a href="#"><img src="img/阿狸.jpg" ></a></li>
				<li><a href="#"><img src="img/蜘蛛女皇伊莉絲-女巫.jpg" ></a></li>
				<li><a href="#"><img src="img/LOL英雄酒館.png" ></a></li>
			</ul>
			<!-- 小圓圈 -->
			<ol class="circle"></ol>
		</div>
	</body>
</html>
           
* {
	margin: 0;
	padding: 0;
	box-sizing: border-box;
}
/* 去掉li的小圓點 */
li {
	list-style:none
}

.focus {
	position: relative;
	width: 1024px;
	height: 400px;
	/* background-color: purple; */
	margin: auto;
	margin-top: 50px;
	overflow: hidden;
}

.focus ul {
	position: absolute;
	top: 0;
	left: 0;
	width: 800%;
}

.focus ul li {
	float: left;
}
.focus ul li img {
	width: 1024px;
}

.focus ol {
	position: absolute;
	height: 20px;
	/* right: 20px; */
	right: 42%;
	bottom: 20px;
	text-align: center;
	padding: 5px;
}

.focus ol li {
	display: inline-block;
	border-radius: 50%;
	width: 20px;
	height: 20px;
	line-height: 20px;
	background-color: #fff;
	margin: 5px;
	cursor: pointer;
}

.focus ol .current {
	background-color: orangered;
}

/* 左右按鈕 */
.arrow-l,
.arrow-r {
	display: none;
	position: absolute;
	top: 50%;
	/* margin-top: -20px; */
	width: 40px;
	height: 60px;
	background: rgba(255, 255, 255, 0.3);
	text-align: center;
	/* line-height: -10; */
	color: black;
	font-size: 40px;
	text-align: center;
	text-decoration: none;
	z-index: 2;
	
}

.arrow-r {
	right: 0;
}
           
window.addEventListener('load',function() {
	// 擷取元素
	var arrow_l = document.querySelector('.arrow-l');
	var arrow_r = document.querySelector('.arrow-r');
	var focus = document.querySelector('.focus');
	var focusWidth = focus.offsetWidth;
	
	// 滑鼠經過 focus 就顯示隐藏左右按鈕
	focus.addEventListener('mouseenter',function() {
		arrow_l.style.display = 'block';
		arrow_r.style.display = 'block';
		// 滑鼠經過停止輪播
		clearInterval(timer);
		timer = null; // 清除定時器變量
	});
	focus.addEventListener('mouseleave',function() {
		arrow_l.style.display = 'none';
		arrow_r.style.display = 'none';
		// 滑鼠離開繼續輪播
		timer = setInterval(function() {
			// 手動調用點選事件
			arrow_r.click();
		}, 2000);
	});
	
	// 動态生成小圓圈 有幾張圖檔就生成幾個小圓點
	var ul = focus.querySelector('ul');
	var ol = focus.querySelector('.circle');
	
	for (var i = 0; i < ul.children.length; i++) {
		// 建立li
		var li = document.createElement('li');
		// 記錄目前小圓圈的索引号 通過自定義屬性來做
		li.setAttribute('index',i);
		// 把li插入到ol裡面
		ol.appendChild(li);
		// 排他思想 直接生成小圓圈的同時直接綁定點選事件
		li.addEventListener('click',function() {
			// 幹掉所有人 把所有的 li 清除 current 類名
			for (var i = 0; i < ol.children.length; i++) {
				ol.children[i].className = '';
			}
			// 留下我自己 目前的li設定為 current 類名
			this.className = 'current';
			// 點選小圓圈,移動圖檔 移動的是ul
			// ul的移動距離 小圓圈的索引号 乘以 圖檔的寬度 注意是負值
			// 點選某個li 就拿到目前li的索引号
			var index = this.getAttribute('index');
			// 點選了某個li就把這個li的索引号給num
			num = index;
			// 點選了某個li就把這個li的索引号給circle
			circle = index;
			
			animate(ul,-index * focusWidth);
		})
	}
	// 把ol裡面的第一個li的類名設定為current
	ol.children[0].className = 'current';
	// 克隆第一張圖檔放到ul最後面
	var first = ul.children[0].cloneNode(true);
	ul.appendChild(first);
	// 點選右側按鈕,圖檔滾動一張
	var num = 0;
	// circle控制小圓圈的播放
	var circle = 0;
	
	// 節流閥
	var flag = true;
	// 右側按鈕
	arrow_r.addEventListener('click',function() {
		if(flag) {
			flag = false; // 關閉節流閥
			// 如果走到最後複制的一張圖檔,此時 ul快速複原left為0
			if (num == ul.children.length - 1) {
				ul.style.left = 0;
				num = 0;
			}
			num++;
			animate(ul,-num * focusWidth,function() {
				flag = true;
			});
			// 點選右側圖檔按鈕,小圓圈随着一起變化
			circle++;
			// 如果circle==ol.children.length說明走到最後我們克隆的這張圖檔了,就複原
			if (circle == ol.children.length) {
				circle = 0;
			}
			// 調用函數
			circleChange();
		}
		
	});
	
	// 左側按鈕
	arrow_l.addEventListener('click',function() {
		if (flag) {
			flag = false;
			// 如果走到最後複制的一張圖檔,此時 ul快速複原left為0
			if (num == 0) {
				num = ul.children.length - 1;
				ul.style.left = -num * focusWidth + 'px';
			}
			num--;
			animate(ul,-num * focusWidth,function() {
				flag = true;
			});
			
			// 點選右側圖檔按鈕,小圓圈随着一起變化
			circle--;
			// 如果circle==ol.children.length說明走到最後我們克隆的這張圖檔了,就複原
			// if (circle < 0) {
			// 	circle = ol.children.length - 1;
			// }
			circle = circle < 0 ? ol.children.length - 1 : circle;
			// 調用函數
			circleChange();
		}
	});
	
	// 清除圓圈函數
	function circleChange() {
		// 清除其餘小圓圈的current類名
		for (var i = 0; i < ol.children.length; i++) {
			ol.children[i].className = '';
		}
		// 留下目前小圓圈的current類名
		ol.children[circle].className = 'current';
	}
	
	// 自動播放輪播圖
	var timer = setInterval(function() {
		// 手動調用點選事件
		arrow_r.click();
	}, 2000);
	
	// 簡單動畫函數封裝obj目标對象 target 目标位置
	// 給不同的元素指定了不同的定時器
	function animate(obj,target,callback) {
	// 當不斷點選按鈕,這個元素的速度會越來越快,因為開啟了太多的定時器
	// 解決方案是:讓我們元素隻有一個定時器執行
	// 先清除以前的定時器,隻保留目前的一個定時器執行
		clearInterval(obj.timer);
		obj.timer = setInterval(function() {
		// 步長值寫道定時器的裡面
		var step = (target - obj.offsetLeft) / 10;
		// 把步長值改為整數 不要出現小數的問題
		step = step > 0 ? Math.ceil(step) : Math.floor(step);
		if(obj.offsetLeft == target) {
			// 停止動畫 本質是停止定時器
			clearInterval(obj.timer);
			// 回調函數寫到定時器結束裡面
			// if (callback) {
			// 	// 調用函數
			// 	callback();
			// }
			callback && callback();
		}
		// 把每次加1這個步長值改為一個慢慢變小的值,步長公式:(目标值-現在的位置)/ 10
		obj.style.left = obj.offsetLeft + step + 'px';
		}, 15);
	}
})
           

傳回頂部

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			.slider-bar {
				position: absolute;
				left: 50%;
				top: 300px;
				margin-left: 600px;
				width: 45px;
				height: 130px;
				background-color: pink;
			}
			
			.w {
				width: 1200px;
				margin: 10px auto;
			}
			
			.header {
				height: 150px;
				background-color: purple;
			}
			
			.banner {
				height: 250px;
				background-color: skyblue;
			}
			
			.main {
				height: 1000px;
				background-color: yellowgreen;
			}
			
			span {
				display: none;
				position: absolute;
					bottom: 0;
			}
		</style>
	</head>
	<body>
		<div class="slider-bar">
			<span class="goBack">傳回頂部</span>
		</div>
		<div class="header w">頭部區域</div>
		<div class="banner w">banner區域</div>
		<div class="main w">主體部分</div>
		<script type="text/javascript">
			// 擷取元素
			var sliderbar = document.querySelector('.slider-bar');
			var banner = document.querySelector('.banner');
			// banner.offsetTop就是被卷去頭部的大小一定要寫到滾動的外面
			var bannerTop = banner.offsetTop;
			// 當側邊欄固定定位之後應該變化的數值
			var sliderbarTop = sliderbar.offsetTop - bannerTop;
			// 擷取main主體元素
			var main = document.querySelector('.main');
			var goBack = document.querySelector('.goBack');
			var mainTop = main.offsetTop;
			
			// 頁面滾動事件 scroll
			document.addEventListener('scroll',function() {
				// window.pageYoffset 頁面被卷去的頭部
				// 當頁面被卷去的頭部大于等于172 此時 側邊欄就要改為固定定位
				if (window.pageYOffset >= 172) {
					sliderbar.style.position = 'fixed';
					sliderbar.style.top = sliderbarTop + 'px';
				} else {
					sliderbar.style.position = 'absolute';
					sliderbar.style.top = '300px';
				}
				// 當頁面滾動到main盒子,就顯示goback子產品
				if (window.pageYOffset >= mainTop) {
					goBack.style.display = 'block';
				} else {
					goBack.style.display = 'none';
				}
			})
			// 當我們點選了傳回頂部子產品,就讓視窗滑動到頁面的最上方
			goBack.addEventListener("click",function() {
				// 裡面的x和y不跟機關,直接寫數字即可
				// window.scroll(0,0);
				animate(window,0);
			});
			
			// 動畫函數
			function animate(obj,target,callback) {
			// 先清除以前的定時器,隻保留目前的一個定時器執行
				clearInterval(obj.timer);
				obj.timer = setInterval(function() {
				// 步長值寫道定時器的裡面
				var step = (target - obj.offsetLeft) / 10;
				// 把步長值改為整數 不要出現小數的問題
				step = step > 0 ? Math.ceil(step) : Math.floor(step);
				if(window.pageYOffset == target) {
					// 停止動畫 本質是停止定時器
					clearInterval(obj.timer);
					// 回調函數寫到定時器結束裡面
					callback && callback();
				}
					// 把每次加1這個步長值改為一個慢慢變小的值,步長公式:(目标值-現在的位置)/ 10
					// obj.style.left = obj.offsetLeft + step + 'px';
					window.scroll(0,window.pageYOffset - step);
				}, 15);
			}
		</script>
	</body>
</html>
           

本地儲存

特性:

  1. 資料存儲再使用者浏覽器中
  2. 設定、讀取資訊友善、甚至頁面重新整理不丢失資料
  3. 容量較大,sessionStorage約5M、localStorage約20M
  4. 隻能存儲字元串,可以将對象JSON.stringify()編碼後存儲

生命周期

簡單來說就是:什麼時候死

sessionStorage

  1. 生命周期為關閉浏覽器視窗
  2. 在同一個視窗(頁面)下資料都可以共享
  3. 以鍵值對的形式存儲使用

存儲資料:

擷取資料:

删除資料:

删除所有資料:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<input type="text">
		<button class="set">存儲資料</button>
		<button class="get">擷取資料</button>
		<button class="remove">删除資料</button>
		<button class="del">清空所有資料</button>
		<script type="text/javascript">
			var ipt = document.querySelector('input');
			var set = document.querySelector('.set');
			var get = document.querySelector('.get');
			var remove = document.querySelector('.remove');
			var del = document.querySelector('.del');
			
			set.addEventListener('click',function() {
				// 當我們點選了之後,就可以把表單裡面的值存儲起來
				var val = ipt.value;
				sessionStorage.setItem('uname',val);
			});
			get.addEventListener('click',function() {
				// 當我們點選了之後,就可以把表單裡面的值擷取過來
				console.log(sessionStorage.getItem('uname'));
			});
			remove.addEventListener('click',function() {
				// 當我們點選了之後,就可以把表單裡面的值删除
				sessionStorage.removeItem('uname');
			});
			del.addEventListener('click',function() {
				// 當我們點選了之後,就可以把表單裡面的值全部删除
				sessionStorage.clear();
			})
		</script>
	</body>
</html>
           

localStorage

  1. 聲明周期永久生效,除非手動删除,否則關閉頁面也會存在
  2. 可以多視窗(頁面)共享(同一浏覽器可以共享)
  3. 以鍵值對的形式存儲使用

存儲資料:

localStorage.setItem(key,value)
           

擷取資料:

删除資料:

localStorage.removeItem(key)
           

删除所有資料:

localStorage.clear()
           
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<input type="text">
		<button class="set">存儲資料</button>
		<button class="get">擷取資料</button>
		<button class="remove">删除資料</button>
		<button class="del">清空所有資料</button>
		<script type="text/javascript">
			var ipt = document.querySelector('input');
			var set = document.querySelector('.set');
			var get = document.querySelector('.get');
			var remove = document.querySelector('.remove');
			var del = document.querySelector('.del');
			
			set.addEventListener('click',function() {
				var val = ipt.value;
				localStorage.setItem('uname',val);
			});
			get.addEventListener('click',function() {
				console.log(localStorage.getItem('uname'));
			});
			remove.addEventListener('click',function() {
				localStorage.removeItem('uname');
			});
			del.addEventListener('click',function() {
				localStorage.clear();
			})
		</script>
	</body>
</html>
           

案例:記住使用者名

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<input type="text" id="username"> <input type="checkbox" name="" id="remember">記住使用者名
		<script type="text/javascript">
			var username = document.querySelector('#username');
			var remember = document.querySelector('#remember');
			
			if (localStorage.getItem('username')) {
				username.value = localStorage.getItem('username');
				remember.checked = true;
			}
			remember.addEventListener('change',function() {
				if(this.checked) {
					localStorage.setItem('username',username.value)
				} else {
					localStorage.removeItem('username');
				}
			})
		</script>
	</body>
</html>
           

繼續閱讀