者:HXGNMSL來源:CSDN原文:https://blog.csdn.net/HXGNMSL/article/details/89076476
Javascript的歷史來源
94年網景公司 研發出世界上第一款瀏覽器。
95年 sun公司 java語言誕生
網景公司和sun合作。
Javascript ===> javascript
JavaScript和ECMAScript的關系
簡單來說ECMAScript不是一門語言,而是一個標準。符合這個標準的比較常見的有:JavaScript、Action Script(Flash中用的語言)
JavaScript的基本結構:
JavaScript的語法:
JavaScript的基礎語法
變量的聲明及使用
數據類型
運算符
邏輯控制語句
注釋
語法規則
變量的聲明語法:
var變量名;
例如:
Var num;
然后進行賦值:num = 10;也可以聲明時直接賦值:
Var num =10;
在JavaScript中,提供了常用的基本數據類型:
undefined 未定義;
null 空;
string 字符串類型;
boolean 布爾類型;
number 數值類型;
運算符:
算數運算符:+、-、*、/、%、++、–;
比較運算符:>、<、> =、< =、==、!=;
邏輯運算符:&&、||、?。?/p>
賦值運算符:=;
邏輯控制語句:
JavaScript的邏輯控制語句也分為兩類:條件結構和循環機構。
條件結構
條件機構分為if結構和switch結構:
If…else
Switch
循環結構
JavaScript的循環結構的執行順序與Java類似,主要包括以下幾種結構:
for循環
while循環
do…while循環
for…inx循環
示例:
for(var i=0;i<10;i++){
Document.write(“*”);
}
輸出結果:**********
循環中斷:
用于循環中斷的語句有以下兩種:
break.
continue.
與Java用法一樣,break是跳出循環,continue是跳入下一次循環。
函數
函數有兩種:一種是系統函數,一種是自定義函數。
常用的系統函數包括:
parseInt():轉換為整數。
parseFloat():轉換為浮點型。
isNaN():判斷非數字。
Eval():計算表達式值。
自定義函數:
自定義函數的語法
function 函數名(參數1,參數2,…){
…//語句
Return 返回值;//可選
}
函數的調用:
函數的調用方式有以下兩種
事件名=函數名(傳遞的實參值),例如:
“函數名()”
直接使用函數名(傳遞的實參值),例如:
var recult = add(2,3);
匿名函數
匿名函數的語法
var sumFun=function(num1,num2){
…
return(nun1,num2);
} ;
在語法中:
var sunFun=function(num1,num2)表示聲明一個變量等于某個函數體。
{…};是把整個函數體放在變量的后面,并把末尾添加一個分號。
匿名函數的調用:
由于匿名函數定義的整個語句,可以像賦值一樣賦給一個變量進行保存,所以可以使用如下方式調用語法中的匿名函數:
var sum=sumFun(2,3)
BOM概述
使用BOM可以移動窗口,改變狀態欄中的文本,執行其他與頁面內容不直接相關的動作。它包含的對象主要有以下幾種;
Window對象
Window對象是指整個窗口對象,可以通過操作Window對象的屬性和方法控制窗口,例如,打開或關閉一個窗口。
History對象
瀏覽器訪問過的歷史頁面對應History對象,通過History對象的屬性和方法實現瀏覽器的前進或后退的功能。
Location對象
瀏覽器的地址欄對應Location對象,通過Location對象的屬性和方法控制頁面跳轉。
Document對象
瀏覽器內的網頁內容對應Document對象,通過Document對象的屬性和方法,控制頁面元素。
Window常用的屬性有:
history:有關客戶訪問過的URL的信息。
location:有關當前URL的信息。
Screen: 有關客戶端的屏幕和顯示性能的信息。
Window對象常用的方法:
prompt():顯示可提示用戶輸入的對話框。
alert():顯示帶有一段消息和一個人“確認”按鈕的警告框。
confirm():顯示帶有一段消息以及“確認”按鈕“取消”按鈕的對話框。
close():關閉瀏覽器窗口。
open():打開一個新的瀏覽器窗口,加載給定URL所指定的文檔。
setTimeout():用于在指定(以毫秒計)后調用函數或計算表達式。
setTneerval():按照指定的周期 (以毫秒計)數來調用函數或計算表達式。
Window對象常用窗口特征屬性
height、width:窗口文檔顯示區的高度、寬度,以像素計。
left、top:窗口的x坐標y坐標,以像素計。
toolbar:yes|no|1|0:是否顯示瀏覽器的工具欄,默認是yes。
scrollbars =yes|no|1|0:是否顯示滾動條,默認是yes。
locationyes|no|1|0:是否顯示地址欄,默認是yes。
status|no|1|0:是否添加地址欄,默認是yes。
menubar|no|1|0:是否顯示菜單欄,默認是yes。
resizable|no|1|0:窗口是否可調節尺寸,默認是yes。
Window對象的常用事件:
onload:一個頁面或一副圖像完成加載。
onmouseover:鼠標指針移到某元素之上。
onclick:單擊某個對象。
onkeydown:某個鍵盤按鍵被按下。
onchange:域的內容被改變。
History對象的方法:
back():加載History對象列表中的上一個URL。
forward():加載History對象列表中的下一個URL。
go():加載History對象列表中的某個具體URL。
Location對象的屬性:
host:設置或返回主機名和當前URL的端口號。
hostname:設置或返回當前URL的主機名。
href:設置或返回完整的URL。
Location對象的方法:
reload():重新加載當前文檔。
replace():用新的文檔替換當前文檔。
Document對象常用的屬性:
referrer:返回載入當前文檔的URL。
URL:返回當前文檔的URL。
Document對象的常用方法:
getElementById():返回對擁有指定id的第一個對象的引用。
getElementsByName():返回帶有指定名稱的對象的集合。
getElementsByTagName():返回帶有指定標簽名的對象的集合。
write():向文檔寫文本、HTML表達式代碼。
內置對象
系統的內置對象有Date對象、Array對象、String對象和Math對象等。
Date:用于操作日期和時間。
Array:用于在單獨的變量名中儲存一系列的值。
String:用于支持對字符串的處理。
Math:用于執行數學任務,包含了若干數字常量和函數。
Date對象:
1:創建日期對象
Date對象包含日期和時間兩個信息,創建日期對象的基本語法有兩種:
創建日期的基本語法1: var 日期實例化=new Date(參數);
創建日期的基本語法2: var 日期實例化=new Date();
Date對象的常用方法:
getDate():從Date對象返回一個月中的某一天,其值介于1到31之間。
getDay():從Date對象返回星期中的某一天,其值介于0到6之間。
getHours():返回Date對象的小時,其值介于0到23之間。
getMinutes():返回Date對象的分鐘,其值介于0到59之間。
getSeconds():返回Date對象的秒數,其值介于0到59之間。
getMonth():返回Date對象的月份,其值介于0到11之間。
getFullYear():返回Date對象的年份,其值為4位數。
getTime():返回自某一時刻(2010年1月1日)以來的毫秒數。
DOM概述
什么是DOM
DOM是文檔對象的縮寫,和語言無關。它提供了訪問、動態修改結構文檔的接口,W3C制定了DOM規范,主流瀏覽器都支持。
使用Core DOM操作節點
訪問節點:
使用getElement系列方法訪問指定節點。
getElementById():返回對擁有指定id的第一個對象的引用。
getElementsByName():返回帶有指定名稱的對象的集合。
getElementsByTagName():返回帶有指定標簽名的對象的集合。
使用層次關系訪問節點。
parenNode:返回節點的父節點。
firstChild:返回節點的首個節點。文本和屬性節點沒有父節點,會返回一個空數組,對于元素節點,若是沒有子節點會返回null。
lastChild:返回節點的最后一個子節點,返回值同firstChild。
操作節點屬性值
CoreDOM的標準方法包括以下兩種:
getAttribute(“屬性名”):獲取屬性值。
getAttribute(“屬性名”,“屬性值”):設置屬性值
創建和增加節點:
創建節點
createElement(tagName):按照給定的標簽名稱創建一個新的元素節點
appendChild(nodeName):向以存在節點列表的末尾添加新的節點。
inserBefore(newNode,oldNode):向指定的節點之前插入一個新的子節點。
cloneNode(deep):復制某個指定的節點。
刪除和替換節點
removeChild(node):刪除指定的節點。
replaceChild(newNode,oldNode):用其他的節點替換指定的節點。
Table對象的屬性和方法
屬性:
rows[]:返回包含表格中所有行的一個數組。
rows[]用于返回表格中所有行的一個數組。
方法:
inserRow():在表格中插入一個新行。
deleteRow():從表格中刪除一行。
數組
數組是具有相同數據類型的一個或多個值得集合
創建數組的語法:
var 數組名稱=new Array(size);
數組的賦值的兩種方式:
先聲明在賦值
var province = new Array(4);
province[0]=“河北省”;
province[1]=“河南省”;
索引也可以使用標識(字符串),例如:
var province=new Array(4);
province[‘河北省’]=“河北省”;
province[‘河南省’]=“河南省”;
聲明時同時初始化
var province=new Array(“河北省”,“河南省”,“湖北省”,“廣東省”);
Array對象的常用屬性和方法:
屬性:
length:設置或返回數組中元素的數目。
方法:
join():把數組的所有元素放入一個字符串,通過一個分隔符進行分割。
sort():對數組的元素進行排序。
一直以來,操作系統的「時間、日期、時區」,是讓很多程序員在開發程序時比較敏感與特別關注的問題。
還記得即將步入 2000 年的“千年蟲”(Year 2000 Problem,簡稱“Y2K”)事件,由于早期的計算機配置比較低,那時為了節省空間就把年份只用后兩位數表示,如 1999 就表示為 99,導致新千年時電腦把 2000 年認為是 1900 年,出現 Bug,進而引發各種各樣的系統功能紊亂甚至崩潰。
2012 年,有用戶發現低內核版 Linux 開啟 NTP 服務器會遇到閏秒 Bug,導致服務器重啟。
2016 年,很多網友“作了一把”,將 iPhone 的日期設置到 1970 年 1 月 1 日,無意中觸發系統 Bug,一時間導致 iPhone 重啟失敗,手機直接變板磚。
就在近日,一個新的關于時間 Bug 出現在 Windows 系統中。據 Ars Technica 報道,有一位挪威數據中心的工程師 Simen 遇到了一個令人費解的時間 Bug, 它會導致 Windows Server 突然將系統時鐘重置到未來 55 天。
時間 Bug 帶來的混亂
事實上,這并不是 Simen 第一次遇到這個問題。
在去年 8 月,Simen 曾遇到過類似的錯誤,當時一臺運行 Windows Server 2019 的機器將時鐘重置到了 2023 年 1 月,但過了沒多久又自動跳回來了。
后來,直到事件日志被清除后才發現這一問題,但那時無法分析具體是什么原因導致的。
現在,他又在一臺運行 Windows Server 2016 的機器上遇到了這個問題。
對于普通用戶而言,時間的錯亂帶來的短暫影響也許可以忽略不計。但是對于工程師而言,卻是一個讓人崩潰的存在。
Simen 的主要工作是在 Windows Server 維護一個路由表(存儲在聯網計算機中的電子表格(文件)或類數據庫),這個路由表實時跟蹤手機號碼從一個運營商轉到另一個運營商的過程。
當服務器出現時間 Bug 時,系統時鐘跳到八周后,這就帶來一個不可估量的后果,譬如,此前尚未遷移的號碼被列入已經遷移、已經轉移的號碼被列為待處理狀態,整個都亂掉了。
無獨有偶
本來以為這只是一個特例,但是搜索一下,網絡上遇到這個問題的工程師不在少數。
去年,有一位名叫 Ken 的工程師也發現了類似的“時間跳躍”現象,當時在 2-3 臺服務器上,時鐘時不時會跳躍到幾周后,甚至有一次直接跳到了 2159 年。
據 Ars Technica 披露,Ken 在一封郵件中寫道:“受此影響的服務器呈指數增長,越來越多。在 5000 臺服務器(虛擬機)中,我們總共有 20 臺左右的服務器(虛擬機)遇到過這種情況。這種情況通常發生在數據庫服務器上。當數據庫服務器在時間上發生跳躍時,就會造成嚴重破壞,只要服務器在時間上有如此大的偏移,備份也就無法運行。對于我們的客戶來說,這一點至關重要。”
除了 Simen 和 Ken 之外,追溯到 2017 年,一位 Reddit 用戶 zanatwo 發帖稱他在一所大學工作,某一天,其發現校園內的幾臺 Windows 10 計算機開始出現錯誤的時間。這些計算機上顯示的時間 Bug 完全是隨機的,在某些情況下,他的設備時間直接跳到了 31 個小時之前。
通過深入分析,當時 Reddit 用戶發現,時間變化與 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\SecureTimeLimits 中的 Windows 注冊表鍵相關。進一步的調查顯示,當一些人試圖訪問大學網站時,這些錯誤報告稱網站使用的有效 SSL 證書無效。
Windows 官方發布的功能惹了禍?
經過排查之后,以上幾位工程師將罪魁禍首統一定位到了 Windows 上一個鮮為人知的功能—— Secure Time Seeding(簡稱 STS)中。
這是微軟在 2016 年引入 Windows 的功能,主要作用就是在 Windows 設備無法通過安全連接與時間服務器通信的情況下,改進對正確時間的記錄。簡單來看,這也是設備在斷電情況下也能保證準確的時間。默認情況下,這一功能在 Windows 系統及服務器下是打開的。
從工作原理來看,為確定當前時間,STS 會調用 SSL(Secure Sockets Layer)握手過程中包含的一組元數據。具體來說,這些數據包括:
ServerUnixTime,日期和時間表示法,顯示自 1970 年 1 月 1 日 00:00:00 UTC 時起已過去的秒數。
從遠程服務器 SSL 證書中獲取的加密簽名數據,顯示該證書是否已根據所謂的 "在線證書狀態協議 "機制被撤銷。
在發布這一功能時,微軟工程師在官方文檔中寫道,他們使用 ServerUnixTime 數據是 "假定它在一定程度上是準確的",但在同一句話中又承認它 "也可能是不正確的"。
為了防止 STS 根據單個不同步遠程服務器提供的數據重置系統時鐘,STS 會隨機穿插 SSL 連接到多個服務器,以得出當前時間的可靠范圍。
然后,該機制會將 ServerUnixTime 與 OCSP(Online Certificate Status Protocol,在線證書狀態協議 )有效期合并,以產生盡可能小的時間范圍,并為其分配置信度分數。
當分數達到足夠高的閾值時,Windows 就會將數據歸類為 STSHC(Secure Time Seed of High Confidence,高置信度安全時間種子)。然后,STSHC 用于監控系統時鐘是否存在 "嚴重錯誤",并對其進行糾正。
盡管 STS 內建了檢查和平衡機制,以確保其提供準確的時間估計,但長期以來工程師遇到的“時間跳躍”事件表明,該功能有時會做出誤差數天、數周、數月甚至數年的胡亂猜測。
在 Ars Technica 報道的文章中,其分享了來自工程師 Ken 遇到時間跳躍時的具體截圖。
第一張圖片中的選定行上方的 "預計安全時間 "條目顯示,Windows 預計當前日期為 2023 年 10 月 20 日,比系統時鐘顯示的時間晚四個多月。然后,STS 會更改系統時鐘,使其與"目標系統時間 "中顯示的錯誤的預計安全時間相匹配。
第二張圖片顯示了類似的情況,其中 STS 將日期從 2023 年 6 月 10 日改為 2023 年 7 月 5 日。
在遇到這一問題后,Ken 和 Simen 都向微軟進行了反饋,遺憾的是,他們并沒有得到實質性的回應與解決方案。
微軟工程師個人曾發出警告:主動關閉 STS 功能
那要問有沒有解決方法,其實去年一位微軟 Windows 高級工程師 Ryan Ries 發過推文提供過用戶,其寫到“大家好,如果你們管理 Active Directory 域控制器,我想給你們一些非官方的建議,這完全是我的個人意見:在您的 DC 上禁用 w32time 的 STS?!?/span>
當有網友進一步詢問原因時,Ryan Ries 表示,「因為在它咬你的屁股之前,這只是一個時間問題」。
這也不禁讓人好奇,連微軟自家工程師都覺得這個功能有問題,為什么官方還有做保留。
就在眾人存疑時,微軟在給 Ars Technica 的一份聲明中寫道:
STS 功能是一種基于啟發式的計時方法,在某些軟件/固件/硬件計時失效的情況下也有助于校正系統時間。該功能已在所有默認 Windows 配置中默認啟用,并已證明在默認配置中發揮了預期功能。
每次部署的時間分配都是獨一無二的,客戶通常會根據自己的特殊需求來配置機器。鑒于 "STS"的啟發式性質以及客戶可能使用的各種部署,我們提供了禁用該功能的選項,以滿足客戶的需求。我們的理解是,在客戶遇到 STS 問題的部署中,很可能存在獨特、專有、復雜的因素,而這些客戶并不能從目前實施的這一功能中受益。在這些個別情況下,我們只能建議在部署中禁用該功能。
具體來看,要禁用 STS,可以在受影響的機器上設置一個注冊表項。這是 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config 目錄中的 UtilizeSslTimeData 密鑰,其類型為 REG_DWORD。如果設置為 0,則停用 STS。如果設置為 1,則可以重新激活該功能。
STS 的異常,有沒有解決方案?
截至目前,似乎除了關閉此功能之外,并沒有太過合適的解決方案,因此,很多人對于微軟的回應并不買賬。在 HN 上,網友也展開了激烈的討論,甚至有人吐槽:是時候應該買塊手表來核對服務器上的時間了!
另外,有網友 @theqmann 分析認為,「這聽起來像是一種統計方法,如果在給定時間內收到 N 個時間戳相似的數據包/連接,就會改變時鐘。我可以看到這樣一個問題:一臺 Windows Server 每分鐘全天候提供數千或數百萬個 OpenSSL 數據包,而它恰好隨機接收到 N 個數據包,這些數據包彼此非常接近,足以滿足統計閾值的要求。通過隨機跳轉,連續跳轉十多次時間都是有可能的」。
@jmuguy 則表示:
在我做 IT 人員的這些年里,Windows Time 是我處理過的最煩人的事情之一。注冊和取消注冊 w32time,嘗試不同的 NTP 服務器。試圖弄明白為什么域系統無法從 DC 獲取時間。這總讓人感覺很......愚蠢。在設備上設置正確的時間肯定沒那么復雜。事實證明,并不復雜,除非你使用的是 Windows 系統。有點諷刺的是,如今我唯一需要處理的 Windows 系統就是我的游戲電腦。它拒絕與 time.windows.com 同步。
除了 Windows 系統之外,還有人稱在 Linux 中也遇到了同樣的問題。
@nicolaslem 表示:
我的 Linux 筆記本電腦有時也會遇到類似的問題,把電腦從睡眠中喚醒時,時間會跳到 2077 年。我猜這是硬件故障,因為它并不經常發生,但一旦發生就會造成很大影響。我無法想象在生產服務器上發生類似情況會有多大影響。
你是否遇到過類似的問題?
參考:
https://arstechnica.com/security/2023/08/windows-feature-that-resets-system-clocks-based-on-random-data-is-wreaking-havoc/
https://news.ycombinator.com/item?id=37151220
https://www.reddit.com/r/sysadmin/comments/61o8p0/system_time_jumping_back_on_windows_10_caused_by/
ouseout和mouseleave的區別
二者都是鼠標移出。mouseout冒泡。 mouseleave不冒泡。(出去冒泡,離開不冒泡)
mouseout對應上面的mouseover ,mouseleave對應上面的mouseenter。
注冊事件的第二種方法(監聽法)
就是誰發生、怎么發生、發生了什么 的第二種表達方式。
誰發生.addEventListener(怎么發生,發生了什么的函數)
//例如上面的唐伯虎點秋香例子
btn.addEventListener('click', function() {
alert('點秋香');
})
element.innerText
//從起始位置到終止位置的內容。但它去除html標簽,同時空格和換行也會去掉
element.innerHTML
//起始位置到終止位置的全部內容,包括html標簽,同時保留空格和換行
<p>2333</p>
<script>
var p = document.getElementByTagName('p');
console.log(p.innerText);
console.log(p.innerHTML);
</script>
常見元素的屬性操作
三種操作情況:
innerText 、innerHTML 改變元素內容
src、 href
id、alt、title
表單元素的屬性操作
利用DOM可以操作如下表單元素的屬性:
type , value , checked , selected , disabled
<body>
<button>按鈕</button>
<input type="text" value="輸入內容" />
<script>
//1,獲取元素
var btn = document.querySelector('button');
var inp = document.querySelector('input');
//2,注冊事件--誰發生 怎么發生 發生什么
btn.addEventListener('click', function() {
//inp.innerHTML = '被點擊了'; 這個是 普通盒子 比如div標簽里面的內容被修改,不是value里的內容被改變
//表單里面的值 文字內容是通過valve來修改的
inp.value = '我被點擊了';
//如果想要某個表單被禁用,不能重復點擊disabled 我們想要這個按鈕 button禁用
//btn.disbled = true; 這樣就被禁用了
this.disabled = true;//這里的this就是btn,因為是btn發生的,這里的this就特指btn了。
//this指向的是發生的那個元素 btn
})
</script>
</body>
案例:京東登陸界面的密碼表單輸入密碼時,默認不顯示密碼。點擊小眼睛圖標時,顯示密碼。再點擊又不顯示密碼。
//2,注冊事件 誰發生 怎么發生 發生什么
var flag = 0;
eye.addEventListener('click', function() {
//每次點擊 flag一定要變化
if(flag == 0) {
pwd.type = 'text';
eye.src = '---';
flag = 1;//這里就是要變化了。原來是0,這里就要變成1
} else {
pwd.type = 'password';
eye.src = '---';
flag = 0;//這里又變化了。原來是1,點過一次就變成0了
}
})
樣式屬性操作
我們可以通過JS修改元素的大小、顏色、位置等樣式。
element.style = ’ ';行內樣式操作
element.className 類名樣式操作
注意:
JS 里面的樣式采取駝峰命名法 比如 fontSize , backgroundColor 。注意,這里沒有連接的 - 了。
JS修改style 樣式操作,產生的是行內樣式,css權重比較高。
className 會直接更改元素的類名,會覆蓋原先的類名。
第3條里,如果原來的類名還想保留,那就可以這樣做,假如原來的類名是class=‘first’ ,現在要用的是class='change’并且不想把原來的first類型替換掉,那就寫成 元素.className = ‘first change’ 就闊以了。
<body>
<div></div>
<script>
//1,獲取元素
var div = document.querySelector('div');
//2,注冊事件。誰發生 怎么發生 發生什么
div.onclick = function() {
//div.style里面的屬性 采取駝峰命名法
this.style.backgroundColor = 'purple';
this.style.width = '200px';
}
</script>
</body>
這里是this是指向函數的調用者,即div在調用這個函數。 相當于div.style (如上圖的div)
如果調用者不是當前的元素,就不能用this了。(如下圖function里的box.style 就不能寫成this.style)
因為是btn在調用函數,然后讓box產生變化。 如果用了this,就是指btn在發生變化了。所以這里不能用this。
當一個元素需要更改的樣式較多時,適合用element.className來完成。
<head>
<style>
.change {
background-color: purple;
color: #fff;
font-size: 25px;
margin-top: 100px;
}
</style>
</head>
<body>
<div>文本</div>
<script>
//當元素樣式較多或者功能復雜的情況下,
//使用element.className獲得修改元素樣式,
var div = document.querySelector('div');
div.onclick = function() {
this.className = 'change';
}
</script>
</body>
如果有同一組元素,我們想要其中一個元素實現某種樣式的情況下,不想讓其他同樣的元素跟著實現這種樣式,就需要用到循環的排他思想算法:
<ul class='baidu'>
<li><img src='1' /></li>
<li><img src='1' /></li>
<li><img src='1' /></li>
</ul>
<script>
//1,獲取元素
var imgs = document.querySelector('.baidu').querySelectorAll('img');
//console.log(imgs);
//2,循環注冊事件
for(var i = 0; i < imgs.length; i++) {
imgs[i].onclick = function() {
//this.src 就是我們點擊的圖片的路徑
//console.log(this.src);
//把這個路徑this.src給body就可以了
document.body.style.backgroundImage = 'url(' + this.src + ')';
}
}
</script>
說白了,就是先讓包括自己的所有人都不顯示,然后再讓自己顯示。 這樣在自己顯示的時候,別人就不顯示了。
全選反選案例:
<script>
//1,全選和取消全選的做法:
//讓下面所有復選框的checked屬性(選中狀態) 跟隨 全選按鈕即可
//獲取元素
var j_acAll = document.getElementById('j_cbAll');
var j_tbs = document.getElementById('j_tb').getElementByTagName('input');
//即 選出下面所有的復選框
//注冊時間 誰發生 怎么發生 發生什么
j_cbAll.onclick = function() {
//this.checked 它可以得到當前復選框的選中狀態
//如果是true 就是選中, 如果是false 就是未選中
console.log(this.checked);
for(var i = 0; i < j_tbs.length; i++) {
j_tbs[i].checked = this.checked;
}
}
//2,下面的復選框需要全部選中,上面全選才能選中做法:
//給下面所有復選框綁定點擊事件,每次點擊,都要循環看是否都選中了
for(var i = 0; i < j_tbs.length; i++) {
j_tbs[i].onclick = function() {
//flag控制全選按鈕是否選中
var flag = true;
//每次點擊下面的復選框都要循環檢查這4個小按鈕是否全被選中
for(var i = 0; i < j_tbs.length; i++) {
if( !j_tbs[i].checked) {
flag = false;
break;
//退出for循環 這樣可以提高運行效率
//因為只要一個沒有選中,剩下的就無需再循環判斷了
}
}
j_cbAll.checked = flag;
}
}
</script>
//每次點擊,都要循環
操作屬性
自定義屬性的操作
獲取屬性值
獲取、設置、移除元素屬性的應用例子:
<body>
<div id="demo" index="1"></div>
<script>
var div = document.querySelector('div');
//1,獲取元素的屬性值
//(1)element.屬性
console.log(div.id);//demo
//(2)element.getAttribute('屬性')
//程序員自己添加的屬性,我們稱為自定義屬性,比如這里的 index
console.log(div.getAttribute('id'));//demo
console.log(div.getAttribute('index'));//1
//2,設置元素的屬性值
//(1)element.屬性 = ‘值’;
div.id = 'test';
div.className = 'navs';
//(2)element.setAttribute('屬性','值');
//主要針對自定義屬性
div.setAttribute('index', 2);
div.setAttribute('class', 'footer');
//class特殊 這里寫的就是class 不是className
//3,移除屬性 element.removeAttribute('屬性');
div.removeAttribute('index');
</script>
</body>
<script>
//獲取元素
var tab_list = document.querySelector('.tab_list');
var lis = tab_list.querySelectorAll('li');
var items = document.querySelectorAll('.item');
//for循環綁定點擊事件
for(var i = 0; i < lis.length; i++) {
//開始給5個小li設置索引號index
lis[i].setAttribute('index',i);
lis[i].onclick = function() {
//1,上面的模塊選項卡,點擊某一個,當前這個底色會是紅色,其他選項卡不變色。
//所以用到排他思想。干掉所有人,其余的li清除class這個類
for(var i = 0; i < lis.length; i++) {
lis[i].className = '';
}
//留下我自己
this.className = 'current';
//2,下面的顯示內容模塊
var index = this.getAttribute('index');
console.log(index);
//干掉所有人 讓其余的item 這些div 隱藏
for(var i = 0; i < items.length; i++) {
items[i].style.display = 'none';
}
//留下我自己 讓對應的item顯示出來
items[index].style.display = 'block';
}
}
</script>
關于自定義屬性
H5自定義屬性
自定義屬性目的:是為了保存并使用數據。有些數據可以保存到頁面中而不用保存到數據庫中。
H5規定自定義屬性data- 開頭做為屬性名并且賦值。說白了就是,自定義屬性要用data- 做開頭。比如:
<div data-index="1"></div>
或者使用JS設置:
element.setAttribute('data-index', 2)
1,element.getAttribute(‘data-index’) 兼容性好
2,H5新增 element.dataset.index 或者element.dataset[‘index’] , ie11才開始支持,而且只能取data- 開頭的自定義元素屬性。
如果自定義屬性里有多個 - 連接的單詞,我們獲取的時候,采取駝峰命名法。如 div.dataset.listName 或 div.dataset[‘listName’]
網頁中的所有內容都是節點(標簽,屬性,文本,注釋,空格等),在DOM中,節點使用node來表示。
HTML DOM樹中的所有節點均可通過JS進行訪問,所有HTML元素(節點)均可被修改,也可以創建或刪除。
一般地,節點至少擁有nodeType(節點類型),nodeName(節點名稱)和nodeValue(節點值)這三個基本屬性。
我們實際開發中,節點操作主要操作的是元素節點。
節點層級
利用DOM樹可以把節點劃分為不同的層級關系,常見的是父子兄弟層級關系。
node.parentNode
<div class="demo">
<div class="box">
<span class="erweima">X</span>
</div>
</div>
<script>
//1,父節點parentNode
var erweima = document.querySelector('.erweima');
//var box = document.querySelector('.box');
//得到的是離元素最近的父級節點(親爸爸)
//如果找不到父節點,就返回null
console.log(erweima.parentNode);
</script>
有兩種獲得方式,標準和非標準。
第一種: parentNode.childNodes(標準)
//雖然是標準的,但是不提倡使用
parentNode.childNodes 返回包含指定節點的子節點的集合。該集合為即時更新的集合。
注意:返回值里面包含了所有的子節點,包括元素節點,文本節點(文字,空格,換行等)等。
如果只想要獲得里面的元素節點,則需要專門處理。所以我們**一般不提倡使用childNodes** 。 專門處理需要的代碼:
var ul = document.querySelector('ul');
for(var i = 0; i < ul.childNodes.length; i++) {
if(ul.childNodes[i].nodeType == 1) {
//即 ul.childNodes[i]是元素節點
console.log(ul.childNodes[i];
}
}
第二種: parentNode.children(非標準)
//雖然是非標準,但是可以得到我們想要的元素節點,
//所以推薦使用這個
parentNode.children是一個只讀屬性,返回所有子元素節點,其余節點不返回。所以重點掌握這個方法。
實際開發中,firstChild 和 lastChild 包含其他節點,操作不方便,而firstElementChild 和 lastElementChild又有兼容性問題。那么我們如何獲取第一個子元素節點或最后一個子元素節點呢?
解決方案:
1.獲取第一個子元素節點, parentNode.children[0];
2,獲取最后一個子元素節點,
parentNode.children[parentNode.children.length - 1]
這樣既可以獲得想要的元素節點,又不存在兼容性問題。
節點操作案例:
<script>
//1,獲取元素
var nav = document.querySelector('.nav');
var lis = nav.children;//得到4個小li
//2,注冊循環事件 點誰誰發生
for(var i = 0; i < lis.length; i++) {
lis[i].onmouseover = function() {
this.children[i].style.display = 'block';
}
lis[i].onmouseout = function() {
this.children[i].style.display = 'none';
}
}
</script>
1和2 取兄弟節點的時候,會把空格文本節點也取到。不適合用。
3和4取出來的確實是想要的兄弟節點,但是會有兼容性問題。
如何解決兼容性問題?
需要自己封裝一個函數。
function getNextElementSibling(element) {
var el = element;
while(el == el.nextSibling) {
if(el.nodeType === 1) {
return el;
}
}
return null;
}
不過兄弟節點用的較少。
document.createElement('tagName');
創建 由tagName指定的HTML元素。因為這些元素原先不存在,是根據我們的需求 動態生成的,所以我們也稱為動態創建元素節點。
<body>
<ul>
<li>2333</li>
</ul>
<script>
//1,創建元素節點
var li = document.createElement('li');
//2,添加后節點 node.appendChild(child)
var ul = document.querySelector('ul');
ul.appendChild(li);
//添加前節點 node.insertBefore(child,指定元素);
var lili = document.creatrElement('li');
ul.insertBefore(lili,ul.children[0]);
</script>
</body>
<body>
<textarea name="" id=""></textarea>
<button>發布</button>
<ul>
</ul>
<script>
//1,獲取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
//2,注冊事件 誰發生 怎么發生 發生什么
btn.onclick = function() {
if(text.value == "") {
alert('內容不能為空!');
return false;
} else {
//(1)創建元素節點
var li = document.createElement('li');
//先創建li 才能賦值
li.innerHTML = text.value;
//(2)添加節點
ul.insertBefore(li,ul.children[0]);
}
}
</script>
</body>
node.removeChild(child)
//舉例:
ul.removeChild(ul.children[0]);
從DOM中刪除一個子節點,返回刪除的節點。
node.cloneNode()
//返回調用該方法的節點的一個副本。
//這里的node是要被克隆的那個元素節點
注意:
<body>
三種動態創建元素的區別
區別:
<!DOCTYPE html>
<html>
<head>
<meta charset="uft-8" />
</head>
<body>
<button>點擊</button>
<div class="inner"></div>
<ul class="create"></ul>
<script>
//1,document.write()創建元素
var btn = document.querySelector('button');
btn.onclick = function() {
document.write('<div>2333</div>');
}
//2,innerHTML 創建元素
var inner = document.querySelector('.inner');
var arr = [];
for(var i = 0; i <= 10; i++) {
arr.push('<a href="">233</a>');
}
inner.innerHTML = arr.join(' ');
//3,document.createElement()創建元素
var create = document.querySelector('.create');
for (var i = 0; i <= 10; i++) {
var li = document.createElement('li');
create.appendChild(li);
}
</script>
</body>
</html>
事件冒泡:IE最早提出,事件開始時由最具體的元素接收,然后逐級向上傳播到DOM最頂層節點的過程。
事件捕獲:網景最早提出,由DOM最頂層節點開始,然后逐級向下傳播到最具體的元素接收的過程。
注意:
1,JS代碼中只能執行捕獲或者冒泡其中的一個階段。二者只能選其一。
2,onclick和attachEvent只能得到冒泡階段。
3,addEventListener()中function()后面的參數,如果是true,表示在事件捕獲階段條用事件處理程序;如果是不寫參數或者參數是false,表示在事件冒泡階段調用事件處理程序。
4,實際開發中我們很少使用事件捕獲,我們更關注事件冒泡。
5,有些事件是沒有冒泡的,比如 onblur,onfocus,onmouseenter,onmouseleave。
什么是事件對象?
eventTarget.onclick = function(event) { };
或
eventTarget.addEventListener('click', function(event) { })
//這個event就是事件對象。可以寫成e或者evt。
//這個參數在前面學習中是沒有寫出來的。
官方解釋:event對象代表事件的狀態,比如鍵盤按鍵的狀態,鼠標的位置,鼠標按鈕的狀態。
簡單理解:事件發生后,跟事件相關的一系列信息數據的集合都放到這個對象里面,這個對象就是事件對象event,它有很多屬性和方法。
比如:
1,誰綁定了這個事件。
2,鼠標觸發事件的話,會得到鼠標的相關信息,如鼠標位置。
3,鍵盤觸發事件的話,會得到鍵盤的相關信息,如按了哪個鍵。
這個event是個形參,系統幫我們設定為事件對象,不需要傳遞實參過去。
當我們注冊事件時,event對象就會被系統自動創建,并依次傳遞給事件監聽器(即事件處理函數)。
兼容性問題
事件對象本身的獲取存在兼容性問題:
1,標準瀏覽器中是瀏覽器給方法傳遞的參數,只需要定義形參3 就可以獲得到。 2,在IE6~8中,瀏覽器不會給方法傳遞參數,如果需要的話,需要到window.event中獲取查找。
解決:
e = e || window.event;
事件冒泡:開始時由最具體的元素接收,然后逐級向上傳播到DOM最頂層節點。
事件冒泡本身的特性,會帶來壞處,也會帶來好處,需要我們靈活掌握。
常用的是標準寫法。IE瀏覽器因為兼容問題,不經常用。如果用了非標準寫法,可以調試一下兼容性:
if(e && e.stopPropagation) {
e.stopPropagation();
} else {
window.event.cancelBubble = true;
}
用法:
<body>
<div class="father">
<div class="son">son兒子</div>
</div>
<script>
//常見事件對象的屬性和方法
//阻止冒泡 dom 推薦的標準 stopPropagation()
var son = document.querySelector('.son');
son.addEventListener('click', function(e) {
alert('son');
e.stopPropagation();//停止傳播
e.canselBubble = true;//非標準 取消泡泡
},false);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
},false);
document.addEventListener('click', function() {
alert('document');
}
</script>
</body>
事件委托也稱為事件代理,在jQuery里面稱為事件委派。
不是每個子節點單獨設置事件監聽器,而是事件監聽器在其父節點上,然后利用冒泡原理影響設置每個子節點。
比如,給ul注冊點擊事件,然后利用事件對象的target來找到當前點擊的li,因為點擊li,事件會冒泡到ul上,ul有注冊事件,就會觸發事件監聽器。
我們只操作了依次DOM,提高了程序的性能。
<body>
<ul>
<li>2333</li>
<li>2333</li>
<li>2333</li>
<li>2333</li>
</ul>
<script>
//事件委托的核心原理:給父節點添加監聽器,
//利用事件冒泡影響每一個子節點。
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
//alert('2333');
//e.target 可以得到我們點擊的對象
e.target.style.backgroundColor = 'pink';
})
</script>
</body>
event對象代表事件的狀態,跟事件相關的一系列信息的集合?,F階段我們主要是用鼠標事件對象mouseevent和鍵盤事件對象keyboardevent。
<style>
img {
position: absolute;
top: 2px;
}
</style>
<body>
<img src=''>
<script>
var pic = document.querySelector('img');
document.addEventListener('mousemove', function(e) {
var x = e.pageX;
var y = e.pageY;
console.log(x, y);//輸出x 和 y坐標
//千萬不要忘記給left和top添加px單位!
pic.style.left = x + 'px';
pic.style.top = y + 'px';
});
</script>
</body>
注意:onkeydown和onkeyup不區分字母大小寫,onkeypress區分字母大小寫。
在我們實際開發中,我們更多的使用keydown和keyup,它能識別所有的鍵(包括功能鍵)
Keypress不識別功能鍵,但是keyCode屬性能區分大小寫,返回不同的ASCII值。
注意:keydown和keyup在文本框里面的特點:他們兩個事件觸發的時候,文字還沒有落入文本框中。keyup事件觸發的時候,文字已經落入文本框里面了。因為鍵已經松開了。
<body>
<input type="text">
<script>
//核心思路:檢測用戶是否按下了s鍵。
//如果按下了s鍵,就把光標定位到搜索框里面。
//使用鍵盤事件對象里面的keyCode,
//判斷用戶按下的是否是s鍵。
//搜索框獲得焦點:使用js里面的focus()方法
var sch = document.querySelector('input');
document.addEventListener('keyup', function(e) {
if(e.keyCode == 83) {
sch.focus();
}
})
</script>
</body>
--------------------DOM---end------------------------
什么是BOM?
BOM(Brower Object Model)即瀏覽器對象模型。它提供了獨立于內容而與瀏覽器窗口進行交互的對象,其核心對象是window 。
BOM由一系列相關的對象構成,并且每個對象都提供了很多方法和屬性。
BOM缺乏標準,JS語法的標準化阻止是ECMA,DOM的標準化組織是W3C,BOM最初是Netscape(就是網景公司)瀏覽器標準的一部分。
BOM比DOM更大,它包含DOM。
window對象是瀏覽器的頂級對象。它具有雙重角色。
1,它是JS訪問瀏覽器窗口的一個接口。
2,它是一個全局對象。定于在全局作用域中的變量和函數都會變成window對象的屬性和方法。
在調用的時候可以省略window,前面學習的對話框都屬于window對象方法,比如alert() ,prompt()等。
注意:window下的一個特殊屬性 window.name
window對象的常用事件
這樣就可以把js放在任何一個地方了,js代碼都會執行了。
window.onload = function() { }
或者
window.addEventListener('load', function() { })(推薦使用,因為沒有次數限制)
window.onload是窗口(頁面)加載事件,當文檔內容完全加載完成時會觸發該事件(包括圖像,腳本文件,css文件等),就會調用處理函數。
注意:
1,有了window.onload就闊以把JS代碼寫在頁面元素的上方,因為onload是等頁面內容全部加載完畢,再去執行處理函數的。
2,window.onload傳統注冊事件方式只能寫一次,如果有多個,會以最后一個window.onload為準。
3,如果使用window.addEventListener則沒有限制。
另一種情況:(加載較慢的情況)
document.addEventListener('DOMContenLoaded', function() { })
DOMContentLoaded事件觸發時,僅當DOM加載完成時,不包括樣式表,圖片,flash等等。
IE9以上才支持。
如果頁面的圖片很多的話,從用戶訪問到onload觸發可能需要較長的事件,交互效果就不能實現,必然影響用戶的體驗,此時用DOMContentLoaded事件比較合適。
window.onresize = function() {}
window.addEventListener('resize', function() {})
window.onresize是調整窗口大小加載事件,當觸發時就調用的處理函數。注意:1,只要窗口大小發生像素變化,就會觸發這個事件。2,我們經常利用這個事件完成響應式布局。window.innerWidth是當前屏幕的寬度。
window.setTimeout(調用函數,延遲的毫秒數);
setTimeout()方法用于設置一個定時器,該定時器在定時器到期后執行調用函數。
注意:
1,window可以省略。
2,這個調用函數可以直接寫函數,或者寫函數名, 或者 '函數名()'三種形式。但是不推薦最后一種寫法。
3,延遲的毫秒數可以省略,默認是0,如果寫,必須是毫秒數。不需要帶單位。
4,因為定時器可能有很多,所以我們經常給定時器賦值一個標識符。
//語法規范: window.setTimeout(調用函數,延遲時間);
//setTimeout(function() {
// console.log('午時已到');
//}, 2000);
function callback() {
console.log('立即斬首');
}
setTimeout(callback, 3000);
回調函數 callback
window.setTimeout(調用函數,延遲的毫秒數);
setTimeout()這個調用函數,我們也稱為回調函數callback。
普通函數是按照代碼順序直接調用。
而這個函數,需要等待時間,時間到了才能取調用這個函數,因此我們稱為回調函數。
簡單理解:回調,就是回頭調用的意思。上一件事干完,再回頭調用這個函數。
以前講的element.onclick = function() {}或者element.addEventListener(‘click’, fn);里面的函數也是回調函數。
clearTimeout(定時器名字);
window.clearTimeout(timeout ID)
注意:1,window可以省略。2,里面的參數就是定時器的標識符。
window.setInterval(回調函數,間隔的毫秒數);
setInterval()方法重復調用一個函數,每隔這個時間,就去調用一次回調函數。
這是與setTimeout()最大的不同。setTimeout()定時器只調用一次回調函數。
注意:
1,window可以省略。
2,這個調用函數可以直接寫函數,或者函數名或者采用字符串 ’ 函數名() ’ 三種形式。
3,間隔的毫秒數可以省略,默認是0,如果寫,必須是毫秒數,不用帶單位。
4,因為定時器可能有很多,所以我們經常給定時器賦值一個標識符。
<body>
<div>
<span class="hour">1</span>
<span class="minute">2</span>
<span class="second">3</span>
</div>
<script>
//1,獲取元素
var hour = document.querySelector('.hour');
var minute = document.querySelector('.minute');
var second = document.querySelector('.second');
var inputTime = +new Date('2019-5-1 18:00:00');//用戶輸入時間總的毫秒數
countDown();//現調用一次函數,防止第一次刷新頁面出現空白
//2,開啟定時器
setInterval(countDown, 1000);
function countDown() {
var nowTime = +new Date();
//返回的是當前時間總的毫秒數
var times = (inputTime - nowTime) / 1000;
//times是剩余需要倒計時的總的秒數
var h = parseInt(times / 60 / 60 / % 24);//小時
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>
案例:發送短信驗證
JS是單線程:同一時間只做一件事。代碼是從上到下一行一行的執行。
同步和異步: 最新的js可以創建多個任務了。
為了解決這個問題,利用多核CPU的計算能力,HTML5提出Web Worker 標準,允許JS腳本創建多個線程。于是,JS中 出現了同步和異步。
前一個任務結束后再執行后一個任務,程序的執行順序與任務排列順序是一直的,同步的。比如做飯的同步做法:我們要燒水煮飯,等水開了(10分鐘后),再去切菜,炒菜。
在做一件事情時,因為這件事情會話費很長時間。在做這件事情的同時,還可以去處理其他事情。比如做飯的異步做法,在燒開水的同時,利用這10分鐘,去切菜,炒菜。
同步任務都在主線程上執行,形成一個執行線。
JS的異步是通過回調函數實現的。 一般而言,異步任務有以下三種類型: 1,普通事件,如click,resize等 2,資源加載,如load,error等 3,定時器,包括setTimeout,setInterval等。
異步任務相關回調函數添加到任務隊列中,任務隊列也稱為消息隊列。
執行機制:任務分成同步任務和異步任務。先執行完同步任務,再去執行異步任務。
1,先執行執行棧中的同步任務。
2,異步任務(回調函數)放入任務隊列中。
3,一旦執行棧中的所有同步任務執行完畢,系統就會按照次序讀取任務隊列中的異步任務,于是被讀取的異步任務結束等待狀態,進入執行棧,開始執行。
由于主線程不斷的重復獲得任務、執行任務、再獲取任務、再執行,所以這種機制被稱為事件循環(event loop)。
location對象
URL
統一資源定位符(Uniform Resource Locator,URL)是互聯網上標準資源的地址。互聯網上的每個文件都有一個唯一的URL,它包含的信息指出文件的位置以及瀏覽器應該怎么處理它。
URL的一般語法格式為:
protocol://host[:port]/path/[?query]#fragment
如:
http://www.itcast.cn/index.html?name=andy&age=18#link
第一個頁面:輸入信息的界面
<body>
<form action="index.html">
用戶名:<input type="text" name="uname">
<input type="submit" value="登錄" />
</form>
</body>
第二個頁面:接收信息的界面
<body>
<div></div>
<script>
console.log(location.search);//?uname=andy
//1,先去掉? substr('起始位置', 截取幾個字符);
var params = location.search.substr(1);//uname=andy
//2,利用 = 號把字符串分割為數組 split('=');
var arr = params.split('=');
console.log(arr);//["uname", "ANDY"]
var div = document.querySelector('div');
//3,把數據寫入div中
div.innerHTML = arr[1] + "歡迎您";
</script>
</body>
navigator對象包含有關瀏覽器的信息,它有很多屬性,我們最常用的是userAgent,該屬性可以返回由客戶機發送服務器的user-agent頭部的值。
下面前端代碼可以判斷用戶哪個中斷打開的頁面,實現跳轉:
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobild|BlackBerry|IEMobild|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {
window.location.href = ""; //手機
} else {
window.location.href = ""; //電腦
}
//把這個代碼賦值到<script></script>里面就闊以了。
//要查哪個網頁地址,就把地址補齊到href里。
window對象給我們提供了一個history對象,與瀏覽器歷史紀錄進行交互。該對象包含用戶(在瀏覽器窗口中)訪問過的URL。
history.back();history.forward();history.go(1);
知識點:
offset翻譯過來就是偏移量,我們使用offset系列相關屬性可以動態的得到該元素的位置(偏移)、大小等。
offset系列常用屬性:
offset翻譯過來就是偏移量,我們使用offset系列相關屬性可以動態的得到該元素的位置(偏移)、大小等。
offset系列常用屬性:
只有上和左,沒有下和右。

client翻譯過來就是客戶端,我們使用client系列的相關屬性來獲取元素在可視區的相關信息。通過client系列的相關屬性可以動態的得到該元素的邊框大小、元素大小等。
注意和offset的區別。clientWidth是不含邊框的。
<body>
<script>
//1,立即執行函數:不需要調用,立馬能夠子級執行的函數
function fn() {
console.log(1);
}
fn();
//2,寫法也可以傳遞參數進來
//(function() {})()或者(function() {}())
(function(a, b) {
console.log(a + b);
var num = 10;
})(1, 2);//第二個小括號可以看作是調用函數
(function sun(a, b) {
console.log(a + b);
var num = 10;//局部變量
}(2, 3));
//3,立即執行函數最大的作用就是 獨立創建了一個作用域,
//里面所有的變量都是局部變量,不會右命名沖突的情況。
</script>
</body>
scroll翻譯過來就是滾動的,我們使用scroll系列的相關屬性可以動態的得到該元素的大小、滾動距離等。
常用的是 element.scrollTop和element.scrollLeft。
window.pageXOffset 和 window.pageYOffset屬性,返回文檔在窗口左上角水平和垂直方向滾動的像素。
pageXOffset設置或返回當前網頁相對于窗口顯示區左上角的X位置。pageYOffset設置或返回當前頁面相對于窗口顯示區左上角的Y位置。
pageXOffset 和pageYOffset屬性相當于scrollX和scrollY屬性。
這些屬性是只讀的。
頁面被卷去 的頭部兼容性解決方案
需要注意的是,頁面被卷去的頭部,有兼容性問題,因此被卷去的頭部通常有如下幾種寫法:
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
實現步驟:
<script>
//簡單動畫函數封裝obj目標對象 target 目標位置
function animate(obj, target) {
var timer = setInterval(function() {
if (obj.offsetLeft >= target) {
//運動到一定距離,就停止計時器
clearInterval(timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 200);
}
var div = document.querySelector('div');
//調用函數
animate(div, 300);
</script>
如果多個元素都使用這個動畫函數,每次都要var聲明定時器。我們可以給不同元素使用不同的定時器(自己專門用自己的定時器)
核心原理:利用JS是一門動態語言,可以很方便的給當前對象添加屬性。
<script>
//var obj = {};
//obj.name = 'andy';
//簡單動畫函數封裝obj是目標對象 target 是目標位置
//給不同的元素指定了不同的定時器
function animate(obj, target) {
obj.timer = setInterval(function() {
if(obj.offsetLeft >= target) {
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 200);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
//調用函數
animate(div,300);
animate(span, 200);
</script>
改進版:
<script>
//當我們不斷的點擊按鈕,這個元素的速度會越來越快,因為開啟了太多的定時器
//解決方案就是 讓我們元素只有一個定時器執行
//先清除以前的定時器,只保留當前一個定時器執行
clearInterval(obj.timer);
function animate(obj, target) {
obj.timer = setInterval(function() {
if(obj.offsetLeft >= target) {
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 200);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
//調用函數
animate(div,300);
animate(span, 200);
</script>
防止輪播圖按鈕連續點擊造成播放過快。
節流閥目的:當 上一個函數動畫內容執行完畢,再去執行下一個函數動畫,讓事件無法連續觸發。
核心思路:利用回調函數,添加要給變量來控制,鎖住函數和解鎖函數。
//開始設置一個變量
var flag = true;
if(flag) {
flag = false;
do something...//關閉水龍頭
}
//利用回調函數,動畫執行完畢后,
flag = true;//打開水龍頭
window.scroll(x,y) 整個窗口滾動到文檔中的特定位置。
x是距離文檔左邊的距離,y是距離文檔頂部的距離。x和y都不帶單位。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。