Web API
Web API
一、名詞解釋:
webAPI:
- 使用js來操作html和瀏覽器
? DOM : document object model 文檔對象模型.
? ===> 把一個頁面當做一個對象來看待. 對象有屬性和方法.
? 是用來呈現以及與任意HTML或XML文檔交互的API;
? 通過DOM提供給我們的屬性和方法, 操作網頁內容.
? BOM: browser object model 瀏覽器對象模型
? ====> 把瀏覽器當做一個對象來看待. 瀏覽器的頂級對象就是window
? 通過瀏覽器提供給我們的方法, 操作瀏覽器的功能.
對象:
- 描述事物的特征和行為 具有屬性和方法
文檔:
- 一個頁面就是一個文檔. document
元素:
- 頁面上所有的標簽都叫元素. element
節點:
- 頁面上所有的內容 都叫節點(元素節點 文本節點 屬性節點 注釋節點)
DOM對象(DOM元素):
- 把頁面上的內容(元素/節點)當成對象來看待
DOM樹:
- 描述了元素節點之間的一種層級關系 父子關系或者兄弟關系
document對象:
- 頁面上的頂級對象
元素和節點有什么區別:
DOM節點:
- DOM 文檔是由節點層次結構組成。每個節點可以有父級或子級節點
DOM元素:
- 元素是特定類型的節點,是使用 HTML 文檔中的標記(標簽)編寫的節點
了解一些常見的節點類型:
1. DocumentType類型 —— 文檔類型聲明節點
-
文檔類型聲明節點即文檔最頂部的類型聲明,比如,`。
-
文檔類型聲明節點的nodeType ==10。
-
文檔類型聲明節點的nodeName等于文檔的類型名。
-
文檔類型聲明節點沒有子節點。
2. Document類型 —— 文檔節點
-
在瀏覽器中,document對象是HTMLDocument類型的一個實例,而HTMLDocument繼承自Document類型。
-
docuemnt對象作為文檔的頂層節點,我們稱其為文檔節點。
-
文檔節點的nodeType等于9。
-
文檔節點的nodeName等于'#document'。
3. Element類型 —— 元素節點
-
元素節點的nodeType等于1
-
元素節點的nodeName等于元素的標簽名
-
所有HTML元素都由HTMLElement或其子類型表示,HTMLElement類型繼承自Element類型。
-
HTMLElement類型設定了id、className、title等基本屬性,所有HTML元素都支持這些屬性
4. Text類型 —— 文本節點
-
文本節點的nodeType等于3.
-
文本節點的nodeName等于'#text'
-
文本節點的nodeValue即為包含的文本內容
-
文本節點的父節點是元素節點,沒有子節點
-
文本節點擁有一個length屬性,表示該文本中的字符數
-
空格也會生成文本節點
-
文本節點的創建:document.createTextNode('文本內容')。
-
默認情況下,一個元素節點下最多只能有一個文本節點。
5. Attr類型 —— 屬性節點
-
一般不將其視作DOM樹的一部分
-
從HTML的角度來看,屬性即元素標簽內的特性;從JS的角度看,屬性就是元素節點對象實現和提供的相關節點
-
屬性節點的nodeType等于2.
-
屬性節點的nodeName等于屬性名
-
屬性節點在HTML中沒有子節點
-
在實際開發中,對于屬性的操作我們一般都使用getAttribute()、setAttribute()、removeAttribute()這幾個更加好用的方法。
二、獲取DOM對象
1. 獲取元素的方式
document.querySelector('選擇器')// 作用:返回指定選擇器的第一個DOM對象(元素)document.querySelectorAll('選擇器')// 作用:返回匹配的所有元素的集合// 返回值:是一個偽數組 一堆集合// 偽數組:有length 有索引 沒有數組的pop,shift等方法document.getElementById('id名') document.getElementsByClassName('類名') document.getElementsByTagName('div')/* 特殊元素的獲取 */ body ==> document.body html ==> document.documentElement? console.dir();打印一個對象的所有屬性和方法
2. 屬性選擇器
<input type="text" value="123" data-id="0" data-name="andy"> <input type="password"> const input1 = document.querySelector('input[value]')// console.log(input)console.log(input.dataset) // 自定義屬性集合console.log(input.dataset.name) // 自定義屬性集合console.log(input.dataset.id) // 自定義屬性集合// 獲取元素// document.querySelector('選擇器')// 1. [] 方括號立馬寫上屬性名const input2 = document.querySelector('input[type="password"]')// 2. 方括號里鍵值對 引號可以省略const input3 = document.querySelector('input[type=password]')// 3. 可以直接寫屬性也能獲取到const input4 = document.querySelector('[type=password]')const input5 = document.querySelector('[value="123"]')const input6 = document.querySelector('[data-id]')console.log(input)3. 操作元素內容
innerHTML 識別html標簽
innerText 不識別html標簽
4. 修改標簽樣式屬性
style (權重大 1000)
className
className適合多個樣式都需要修改的情況
也可以清空某個元素的所有類名 div.className =’ ’
classList
- 添加類名:box.classList.add(‘類名’)
- 刪除類名:box.classList.remove(‘類名’)
- 切換類名:box.classList.toggle(‘active’)
三者的使用選擇:
- style 適合修改單個或少部分樣式的時候使用
- className 缺陷會覆蓋原來的類名
- classList 不會覆蓋原來的類名 是追加或者刪除當前的這個類名
三、自定義屬性
- 它獲取到的是一個對象, 存放了所有以**data開頭**定義的自定義屬性
-
element.dataset.屬性名
-
element.dataset[‘屬性名’] (注意:單引號)
四、遍歷對象獲取屬性
const obj = {name: 'pink',age: 20,hobby: '唱歌',key: '234'}for (let key in obj) {console.log(key) //name age hobby keyconsole.log(obj[key]) //'pink' 20 '唱歌' '234'console.log(obj['name']) // 'pink'// 1. 這里的key是一個變量, 每次循環的時候,依次表示每一個屬性名// 第一次循環 key 'name'// 第二次 key 'age'// 第三次 key 'hobby}// 如果我們要直接取屬性的值, 這里, 需要加引號console.log(obj['age'])// 如果不加引號, 表示變量, 找不到age, console.log(obj[age]) // Error 報錯console.log(obj[key]) // Error 報錯console.log(obj['key']) //234console.log(obj.key) //234// ===> 最后記住一句話: obj[key]// 如果不加引號, 表示變量 , // 如果加了引號, 表示對象本身存在的某個屬性名五、計時器setInterval
1. setInterval使用
// 第一種:直接把函數寫在setInterval()里面// 語法: window.setInterval(fn, wait)// window提供的方法 window可以省略window.setInterval(function() {console.log('定時器在走');}, 1000)// 第二種:具名函數 function fn() {console.log('午飯吃什么');}const foo = function() {console.log('好好努力');}setInterval(foo, 1000)思考:
var a = 3; //在頂層函數中聲明變量afunction f() {const a = 2; //在函數體內聲明局部變量areturn new Function("return a*a;"); //無法捕獲局部作用域}console.log(f()()); // 92. 定義函數有幾種方式
// 1. 聲明式function foo(){console.log(1)}btn.addEventListener('click', foo)// 2. 表達式const bar = function(){console.log(2)}btn.addEventListener('click', bar)3. 清除計時器
let timer1 = setInterval(function() {console.log('22222');}, 1000)console.log(timer1); // 定時器有一個返回值 是一個數字 是當前定時器的唯一標識// 這個number標記 從1開始clearInterval(timer1) //清除計時器六、延時器 setTimeout
setTimeout(function() {console.log('大家吃早飯了嘛? ')}, 1000)// 1.2 寫函數名function cb() {console.log('餓了嗎')}const foo = function() {console.log('真的不餓嗎')}// 注意:函數名后面一定不要寫小括號, 寫小括號表示調用let timer1 = setTimeout(cb, 2000)let timer2 = setTimeout(foo, 5000)window.clearTimeout(timerId) // 清除延時器// window可以省略setTimeout 延時時間到了,只調用一次
setInterval 每隔這個延時時間,都會回調一次,會調用很多次,直到清除定時器
七、事件監聽
事件三要素:
事件源:誰 誰觸發了事件
事件類型:什么事件(行為)
事件處理程序:我們要干嘛(事件)
1. 隨機點名案例分析(多種方法解析)
<h2>隨機點名</h2><div class="box"><span>名字是:</span><div class="qs">這里顯示姓名</div></div><div class="btns"><button class="start">開始</button><button class="end">結束</button></div> <!-- 多次重復點擊會開啟多個計時器 速度會隨著點擊的次數增加而加快 且后臺會冗余大量的計時器 --> // 解決方法一: const arr = ['馬超', '黃忠', '趙云', '關羽', '張飛']const start = document.querySelector('.start')const end = document.querySelector('.end')const qs = document.querySelector('.qs')let ilet timerIdstart.addEventListener('click', function() {clearInterval(timerId) // 在每次點擊事件之前 先進行清除計時器 這樣確保每次點擊開始之后 只有一個計時器在進行// 缺點:后臺會冗余大量已經清除的計時器timerId = setInterval(function() {i = Math.floor(Math.random() * arr.length)qs.innerHTML = arr[i]}, 50)if (arr.length === 1) {start.disabled = end.disabled = true}})end.addEventListener('click', function() {clearInterval(timerId)arr.splice(i, 1)}) // 解決方法二: const arr = ['馬超', '黃忠', '趙云', '關羽', '張飛']const start = document.querySelector('.start')const end = document.querySelector('.end')const qs = document.querySelector('.qs')let ilet timerIdlet flag = true// 聲明flag 運用開關思想 來控制后臺啟動計時器的數量start.addEventListener('click', function() {if (flag === false) returnflag = falsetimerId = setInterval(function() {i = Math.floor(Math.random() * arr.length)qs.innerHTML = arr[i]}, 50)if (arr.length === 1) {start.disabled = end.disabled = true}})end.addEventListener('click', function() {clearInterval(timerId)// 對flag進行判斷 是為了防止多次點擊“結束” 導致數組里面的元素全部刪除清空 出現undefinedif (flag) { arr.splice(i, 1)}flag = true}) // 解決方法三: const arr = ['馬超', '黃忠', '趙云', '關羽', '張飛']const start = document.querySelector('.start')const end = document.querySelector('.end')const qs = document.querySelector('.qs')let ilet timerId = 0start.addEventListener('click', function() {if (timerId) return// 就地取材 直接利用現有的timerId變量 運用開關思想 進行判斷timerId++timerId = setInterval(function() {i = Math.floor(Math.random() * arr.length)qs.innerHTML = arr[i]}, 50)if (arr.length === 1) {start.disabled = end.disabled = true}})end.addEventListener('click', function() {clearInterval(timerId)if (timerId) {// 為了防止多次點擊“結束” 導致數組里面的元素全部刪除清空 出現undefinedarr.splice(i, 1)}timerId = 0})2. 輪播圖
<div class="slider"><div class="slider-wrapper"><img src="./images/slider01.jpg" alt="" /></div><div class="slider-footer"><p>對人類來說會不會太超前了?</p><ul class="slider-indicator"><li class="active"></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul><div class="toggle"><button class="prev"><</button><button class="next">></button></div></div></div> // 1. 初始數據const arr = [{url: './images/slider01.jpg',title: '對人類來說會不會太超前了?',color: 'rgb(100, 67, 68)'}, {url: './images/slider02.jpg',title: '開啟劍與雪的黑暗傳說!',color: 'rgb(43, 35, 26)'}, {url: './images/slider03.jpg',title: '真正的jo廚出現了!',color: 'rgb(36, 31, 33)'}, {url: './images/slider04.jpg',title: '李玉剛:讓世界通過B站看到東方大國文化',color: 'rgb(139, 98, 66)'}, {url: './images/slider05.jpg',title: '快來分享你的寒假日常吧~',color: 'rgb(67, 90, 92)'}, {url: './images/slider06.jpg',title: '嗶哩嗶哩小年YEAH',color: 'rgb(166, 131, 143)'}, {url: './images/slider07.jpg',title: '一站式解決你的電腦配置問題!!!',color: 'rgb(53, 29, 25)'}, {url: './images/slider08.jpg',title: '誰不想和小貓咪貼貼呢!',color: 'rgb(99, 72, 114)'}, ]const img = document.querySelector('.slider-wrapper img')const p = document.querySelector('.slider-footer p')const lis = document.querySelectorAll('.slider-indicator li')const footer = document.querySelector('.slider-footer')const prev = document.querySelector('.prev')const next = document.querySelector('.next')let i = 0next.addEventListener('click', function() {i++if (i >= 8) {i = 0}render()})prev.addEventListener('click', function() {i--if (i <= -1) {i = arr.length - 1}render()})function render() {img.src = arr[i].urlp.innerHTML = arr[i].titlefooter.style.backgroundColor = arr[i].colordocument.querySelector('.slider-indicator .active').classList.remove('active')lis[i].classList.add('active')}/* ================== 計時器 ================== */const slider = document.querySelector('.slider')let timer = setInterval(function() {next.click()}, 1000)slider.addEventListener('mouseenter', function() {clearInterval(timer)})slider.addEventListener('mouseleave', function() {timer = setInterval(function() {next.click()}, 1000)})3. 全選按鈕案例
const checkAll = document.querySelector('#checkAll')const cks = document.querySelectorAll('.ck')// 最外層是循環cks.forEach(function(item) {// 點擊全選按鈕checkAll.addEventListener('click', function() {item.checked = checkAll.checked})// 點擊單個按鈕item.addEventListener('click', function() {const arr = document.querySelectorAll('.ck:checked')if (arr.length === cks.length) {checkAll.checked = true} else {checkAll.checked = false}})3. 鍵盤事件(input\change\blur)
- input事件: 在輸入框輸入的時候會實時響應并觸發;
- change事件:在輸入框失去焦點,并且輸入框的值發生變化的時候才會觸發
- blur事件:blur事件是每次失去焦點時觸發,不管輸入框數據有沒有變化;
八、DOM事件對象
事件對象: 當事件發生的時候, 和這個事件相關的所有信息, 都存在這個對象中.
在 DOM 中發生事件時,所有相關信息都會被收集并存儲在一個名為 event 的對象中。這個對象包 含了一些基本信息,比如導致事件的元素、發生的事件類型,以及可能與特定事件相關的任何其他數據。 例如,鼠標操作導致的事件會生成鼠標位置信息,而鍵盤操作導致的事件會生成與被按下的鍵有關的信 息。
這個對象就叫做事件對象. event, 簡寫ev、evt ===> e
event 對象只在事件處理程序執行期間存在,一旦執行完畢,就會被銷毀
1. 事件對象常見的公共屬性與方法
| currentTarget 元素 | 只讀 | 當前事件處理程序所在的元素 |
| preventDefault() 函數 | 只讀 | 用于取消事件的默認行為 |
| stopImmediatePropagation() 函數 | 只讀 | 用于取消所有后續事件捕獲或事件冒泡, 并阻止調用任何后續事件處理程序(DOM3 Events新增) |
| stopPropagation() 函數 | 只讀 | 用于取消所有后續事件捕獲或事件冒泡 |
| target 元素 | 只讀 | 事件目標 |
| type 字符串 | 只讀 | 被觸發的事件類型 |
-
e.target ==> 觸發事件的元素 點擊的是誰 他就指向誰
this ==> 綁定事件的元素
e.currentTarget ==> 綁定事件的元素 等于this
-
type 屬性多用于在一個處理程序處理多個事件
-
preventDefault()與stopPropagation()的區別:
-
preventDefault()方法用于取消默認行為的事件
比如,鏈接的默認行為就是在被單擊時導 航到 href 屬性指定的 URL,如果想阻止這個導航行為,可以在 onclick 事件處理程序中取消;以及submit默認提交行為
-
stopPropagation()方法用于立即阻止事件流在 DOM 結構中傳播,取消后續的事件捕獲或冒泡
例如,按鈕的事件處理程序中調用 stopPropagation(),可以阻止 document.body 上注冊的事件處理程序執行
阻止的是事件的傳播 不會阻止函數內代碼的執行
-
九、函數內部特殊對象(arguments、this)
1. arguments動態參數
-
arguments 是函數內部內置的偽數組變量,它包含了函數調用時傳入的所有實參
- 動態參數,只存在于函數里 是偽數組
- arguments的作用是動態獲取函數傳遞過來的所有實參
- 可以通過for循環一次性得到傳遞過來的實參 function box() {let sum = 0;if (arguments.length == 0) return sum; //如果沒有參數,退出for(var i = 0;i < arguments.length; i++) { //如果有,就累加sum = sum + arguments[i];}return sum; //返回累加結果 } alert(box(5,9,12));
2. this
- this就是一個關鍵字, 是一個變量. 它的值存的是一個對象.
this在標準函數和箭頭函數中有不同的行為。
- 在標準函數中,this 引用的是把函數當成方法調用的上下文對象
- 在箭頭函數中,this引用的是定義箭頭函數的上下文
函數內部 this這個對象的值取決于函數被調用的方式
// 函數內部 this這個對象的值取決于函數被調用的方式// ===> 粗略的規則:誰調用 this指向誰// 1. 普通函數的調用function fn() {console.log(this);}fn() // ===> 相當于window.fn()window.fn()// 2. 函數作為對象的方法調用const obj = {name: 'zjl',fn: function() {console.log(this);}}obj.fn() // obj{}// 2.3 事件綁定中 this指向注冊(綁定)事件元素const btn = document.querySelector('button')btn.addEventListener('click', function() {console.log(this); // <button>this.style.color = 'orange'console.log(btn === this); // true})btn.fn() ==>可以理解為 btn調用了這個函數十、回調函數
本質上: 就是函數, 只是作為函數的參數來進行使用.
-
作為函數的參數傳入
-
一開始不執行, 當滿足某些觸發條件的時候, 才執行.回頭再調用
使用場景:事件綁定 / 事件注冊 / 事件監聽
十一、事件
1. 事件流:
事件在執行過程中的流動路徑(元素在頁面中接收事件的順序)
DOM事件流 三個階段:
? 1. 捕獲階段 從外到內
? 2. 處于目標階段
3. 事件冒泡階段 從內到外2. 事件捕獲:
是最不具體的節點應該最先收到事件,而最具體的節點應該最后收到事件
document - > html - > body - > father - > son(從外到內)
addEventListener(type, listener, true) 第三參數為 true
3. 事件冒泡:
事件從最具體的元素(文檔樹中最深的節點)開始觸發,然后向上傳播至沒有那么具體的元素(文檔)
son - > father - > body - > html - > document(從內到外)
addEventListener(type, listener, false)
4. 事件解綁
// 第一種:傳統方式解綁const btn = document.querySelector('button')btn.onclick = function() {console.log('傳統方式解綁');btn.onclick = null}// 第二種:事件監聽方式的解綁const fn = function() {console.log('事件監聽方式的解綁');btn.removeEventListener('click', fn)}btn.addEventListener('click', fn)// 我們解綁的時候, 需要傳入一個函數名字, 表示解綁誰btn.removeEventListener('click', 沒有函數名)// 建議: 不管是表達式,還是聲明式, 都寫在事件注冊的前面.// 先聲明, 在使用. 函數的定義, 寫在調用的前面 // 事件監聽, 如果直接寫匿名函數, 無法解綁btn.addEventListener('click', function() {console.log('你動不了我')})5. 事件委托
利用事件冒泡 將事件監聽綁定在父元素上 通過父元素來監聽子元素的事件
- 當我們使用事件委托的時候,使用**e.target.**tagName來判斷我們點擊的是否是想要的標簽
- 事件委托的好處(作用):減少事件注冊的次數 提高程序性能
6. 頁面加載事件
- window ==> load 頁面上所有的資源加載完執行 包括css、圖片
- document ==> DOMContentLoaded 只要DOM元素加載完 就執行回調
1. window ==> load
// 等待頁面所有資源都加載完畢后, 才執行回調函數里面的代碼。(DOM元素加載完,CSS, 圖片等都加載完)window.addEventListener('load', function(){// js代碼內容})2. DOMContentLoaded
// 當DOM元素加載完成時, 就會執行回調函數 不包含圖片, 樣式等。document.addEventListener('DOMContentLoaded', function(){// js代碼內容})7. 滾動事件
// 被卷去的頭部 document.documentElement.scrollTop === window.pageYOffset // scrollTop 可讀寫 被檢測的元素.offsetTop// offsetTop 僅可讀 被檢測元素距離頁面頂部的位置8. 立即執行函數
Immediately-Invoked Function Expression (IIFE) 立即執行函數(自執行函數)
作用:
立即執行函數會形成一個單獨的作用域,我們可以封裝一些臨時變量或者局部變量,避免污染全局變量
// 1. 普通函數, 先聲明, 后調用function fn() {console.log('我是普通函數')}fn() // 函數名加() 調用// 2. 立即執行函數 : 不需要調用,立馬執行的函數 // 以() / [] 開頭, 再前面需要加分號!;(function() { /* code */ })();(function() { /* code */ }())// 3. 多個立即執行函數之間, 要用分號隔開 例題: ;(function() {// 如果沒寫關鍵字, 會變為全局變量 成為window的屬性num = 20console.log(num)})()console.log(num) // 20九、處理字符串的屬性與方法
1. 去除字符串空格trim()
- trim() 去除字符串左右兩邊的空格
- 語法: str.trim()
- 返回一個新的字符串,不會改變原來的字符串
2.數組轉換為字符串
toString()
作用: 返回字符串。
join()
- arr.join(分割符)
- 作用: 把數組的所有元素連接成一個字符串, 并返回這個字符串。
- 參數:可以傳一個分割符, 也可以省略
3. 字符轉換為數組split()
let str2 = 'red, blue, purple';console.log(str2.split(',')); // [red, blue, purple]4. 返回指定位置的字符charAt()
var str = "HELLO WORLD"; var n = str.charAt(2) // L// 遍歷字符串里面所有字符for (let i = 0; i < str1.length; i++) {console.log(str1.charAt(i));} // 查找字符串'addjfirfcjasxaodofcjoao'中所有o出現的位置以及次數// 因為indexOf 只能查找到第一個 所以后面的查找 一定是當前索引號+1 從而繼續查找let str = 'addjfirfcjasxaodofcjoao';let index = str.indexOf('o');let num = 0;while (index !== -1) {console.log(index);num++;index = str.indexOf('o', index + 1);// 因為indexOf 只能查找到第一個 所以后面查找 一定是當前索引號+1 從而繼續查找}console.log('o出現的次數是:' + num); // 判斷字符串 出現次數最多的字符 并統計其次數// obj.a=1// obj.b=1// obj.c=1let obj = {};for (let i = 0; i < str.length; i++) {let chars = str.charAt(i);if (obj[chars]) { //o[chars]得到的是屬性值 obj[chars]++;} else {obj[chars] = 1;}}console.log(o);5. 返回字符串首次出現位置indexOf()
- indexOf() 方法可返回某個指定的字符串值在字符串中首次出現的位置
- 如果沒有找到匹配的字符串則返回 -1
- indexOf 從前往后尋找字符串位置
6. 切片
substring()
- 提取字符串中介于兩個指定下標之間的字符
- 返回字符串:[開始處的字符,結束處的字符)
slice(start,end)
- 可提取字符串的某個部分,并以新的字符串返回被提取的部分
- 返回字符串:[start,end)
- start 參數字符串中第一個字符位置為 0, 第二個字符位置為 1, 以此類推
- end 參數如果為負數,-1 指字符串的最后一個字符的位置,-2 指倒數第二個字符,以此類推
substr()
let str1 = '改革春風吹滿地';console.log(str1.substr(2, 3)); // 春風吹7. 替換字符replace()
let str = 'addjfirfcjasxaodofcjoao';// 把字符里面所有的‘f’替換為‘*’while (str.indexOf('f') !== -1) {str = str.replace('f', '*')}console.log(str);8. 將 Unicode 編碼轉為一個字符fromCharCode()
fromCharCode()
- 將 Unicode 編碼轉為一個字符
9. 字符串樣式
let str = "hello world"// length big small fontcolor fontsize bold italics strike刪除線 sub下 sup上// toUpperCase大寫 link charAt concat連接字符串 indexOf lastindexOf slicedocument.write(str.length + "<br>");document.write(str.big().big().italics() + "2".sub() + "<br>");document.write(str.fontcolor('pink') + "<br>");document.write(str.link("http://www.baidu.com") + "<br>");十、Date 對象
1. 實例化
- **實例化:**通過構造函數生成實例對象的過程
- **實例:**實例的例子 具體的某一個對象
通過Star這個構造函數 創建出了劉德華這個具體的明星 這個過程叫做實例化
2. 常見的方法
let date = new Date() date.getFullYear() // 年 date.getMonth() // 月(0~11) date.getDate() // 日(1~31) date.getDay() // 星期(0~6)date.getHours() //時 date.getMinutes() //分 date.getSeconds() //秒 date.getTime() 、date.now() // 時間戳 后者性能更好date.toString()); > "Fri Sep 09 2022 01:04:24 GMT+0800 (中國標準時間)" date.toDateString()); > "Fri Sep 09 2022" date.toLocaleDateString(undefined, options); > "2022年9月9日星期五" date.toLocaleDateString(); > "2022/9/9" date.toLocaleTimeString('en-US'); > "8:47:13 AM" date.toLocaleTimeString(); > "08:47:13"3. 倒計時
<div class="countdown"><!-- <p class="next">今天是2222年2月22日</p> --><p class="title">倒計時</p><p class="clock"><span id="day">00</span><i>:</i><span id="hour">00</span><i>:</i><span id="minutes">25</span><i>:</i><span id="scond">20</span></p><!-- <p class="tips">18:30:00下課</p> --></div> const getCountTime = function() {// 得到當前的時間戳const now = +new Date()const future = +new Date('2022-9-8 09:00:00')const time = (future - now) / 1000// 除以1000是為了得到秒數let d = parseInt(time / 60 / 60 / 24)let h = parseInt(time / 60 / 60 % 24)let m = parseInt(time / 60 % 60)let s = parseInt(time % 60)// 補 0d = d < 10 ? '0' + d : dh = h < 10 ? '0' + h : hm = m < 10 ? '0' + m : ms = s < 10 ? '0' + s : s// 將天、時、分、秒放入盒子const arr = [d, h, m, s]const spans = document.querySelectorAll('span')arr.forEach(function(item, index) {spans[index].innerHTML = item})}getCountTime()setInterval(getCountTime, 1000)十一、節點操作
1. 父節點
文檔: document 一個頁面就是一個文檔 window ==> document ==> html
元素: element 頁面上所有的標簽都叫元素
節點: node 頁面上所有的內容都叫節點 : 元素節點 屬性節點 文本節點 注釋節點
父節點: node.parentNode 返回最近一級的父元素(節點) 如果找不到就返回null
2. 子節點
<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul> // 1. 子節點 (元素/文本/屬性/注釋節點)// 語法: node.childNodes node表示父元素const ul = document.querySelector('ul')console.log(ul.childNodes)// 返回值, 是一個偽數組: 有length, 有索引, 但是沒有數組的pop()/push()等方法// 2. 子元素節點// 語法:node.children// 獲取的是夫元素下的子元素節點(親兒子)// 返回值:也是一個偽數組// 獲取第一個子元素節點console.log(ul.children[0]);// 獲取最后一個子元素節點console.log(ul.children[ul.children.length - 1]);3.兄弟節點
node.parentNode 父節點
node.children 子元素節點(偽數組)
node.previousElementSibling 前一個兄弟元素節點
node.nextElementSibling 后一個兄弟元素節點
4. 增加節點
先創建(元素)節點/標簽,再追加給父元素( 先創建 再追加)
- 父元素.appendChild(要添加的元素)
- 父元素.insertBefore(插入的元素,放在哪個元素前面)
- insertBefore 與 appendChild不能同時對一個克隆對象進行操作
5. 克隆節點
const copy_li1 = li1.cloneNode(true) // 參數為true 為深拷貝面試題:深拷貝與淺拷貝
共同點:復制 1. 淺拷貝:只復制引用,而未復制真正的值。 var arr1 = ['a','b','c','d']; var arr2 = arr1;var obj1 = {a:1,b:2} var obj2 = Object.assign(obj1);2. 深拷貝:是復制真正的值 (不同引用) var obj3 = {a:1,b:2 } var obj4 = JSON.parse(JSON.stringify( obj3 ));6. 刪除節點
- node(父元素).removeChild(子元素)
- 只能刪除父節點下面最近一層的子節點 不能跨級刪除
十二、BOM
- BOM 瀏覽器對象模型, 把瀏覽器(頂級對象 window)當做一個對象
- DOM 文檔對象模型, 把頁面文檔當做一個對象
- 在全局作用域中, 用var聲明的變量, 會成為window的屬性;用const let 聲明的變量,則不會成為window的屬性
- 全局作用域中用function聲明的函數,會成為window對象的方法;用const聲明的函數不會成為window對象的方法
1. location對象
屬性:
? location.href 記錄了URL的完整地址. 可讀寫 , 所以還可以設置==>可以跳轉
e.preventDefault() 阻止默認提交 阻止表單的action跳轉 但是不會阻止代碼的執行 form.action='http://baidu.com'? location.search 獲取"?xxxxx"
? location.hash 獲取的是"#xxxx"
方法
? location.reload() 方法 重新加載, 頁面刷新
? location.reload(true) 表示強制刷新。 清空緩存
2. navigator對象
檢測 userAgent(瀏覽器信息)
userAgent記錄了瀏覽器配置信息, 可以檢測是Android 還是 IOS, 是移動端,還是PC
;(function() {const userAgent = navigator.userAgent// 驗證是否為Android或iPhoneconst android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)// 如果是Android或iPhone,則跳轉至移動站點if (android || iphone) {location.href = 'http://m.itcast.cn'}})();3. history對象
返回上一頁面
history.back(-1):直接返回當前頁的上一頁,數據全部消息,是個新頁面 history.go(-1):也是返回當前頁的上一頁,不過表單里的數據全部還在 history.back(-1) history.back(); //返回前進一頁面
history.back(1) 前進 history.go(1); //前進 history.forward(); //前進4. localStorage 本地存儲
面試題:localStorage 和 sessionStorage 有什么區別? 1. 生命周期 2. 數據共享 3.localStorage 和 sessionStorage的存儲大小, 都是5M-
生命周期: 生命周期永久生效(數據一直存在), 除非手動刪除, 否則關閉頁面也會存在
- 生命周期: 一個對象的創建到清除的過程, 數據存在的周期
-
數據共享: 可以多窗口(頁面)共享 , 同一個瀏覽器,同一個域名(地址)下
-
數據以鍵值對的形式存儲使用 key value, 存的是字符串的形式
- 存數據 localStorage.setItem(key, value) localStorage.setItem('user_name', '劉德華') // 如果key存在, 就是覆蓋修改, 不存在, 就是新增一條數據
- 取數據 localStorage.getItem(key), 返回值就是我們存的value const res = localStorage.getItem('user_name')
- 刪數據 localStorage.removeItem(key) localStorage.removeItem('user_name')
- 清空數據 localStorage.clear()
5. 本地存儲復雜數據類型
復雜數據類型 在存入 localStorage / sessionStorage之前, 必須先轉為字符串
JSON.stringify() : 將對象轉換為JSON格式的字符串
localStorage.setItem('test_obj', JSON.stringify(obj))JSON.parse() : 將JSON格式的字符串, 轉換為對象形式。
const result = JSON.parse(localStorage.getItem('test_obj'))6. sessionStorage 會話存儲
-
生命周期: 關閉瀏覽器窗口, 數據清除
-
數據共享: 在同一個窗口(頁面)下數據可以共享 (前提:同一個域名下)
-
數據以鍵值對的形式存儲使用 key value, 存的是字符串的形式
- 存數據 sessionStorage.setItem(key, value) sessionStorage.setItem('user_name', '劉德華') // 如果key存在, 就是覆蓋修改, 不存在, 就是新增一條數據
- 取數據 sessionStorage.getItem(key), 返回值就是我們存的value const res = sessionStorage.getItem('user_name')
- 刪數據 sessionStorage.removeItem(key) sessionStorage.removeItem('user_name')
- 清空數據 sessionStorage.clear()
十三、事件循環
1. JS是**單線程**的語言:
也就是同一時間只能做一件事件(同步), 所有的工作的順序執行
- 代碼是從上到下,依次執行的, 邏輯是一步一步完成
why JS是單線程?
- JS設計之初, 就是為了做網頁交互, 那么就會操作DOM元素
2. 線程和進程
進程是資源分配的最小單位, 線程是CPU調度的最小單位
進程(process) : 一個進程就是一個正在運行的程序(打開任務管理器)
線程(thread) : 一個進程內執行著的每一個任務 (錄屏程序: 錄聲音,錄畫面)
- 線程是允許應用程序并發執行多個任務的一種機制
- 進程 ==> 火車 , 線程 ==> 車廂
兩者聯系:
3. 同步和異步
同步: 同一時間只能執行一個任務, 上一個任務執行完, 才能執行下一個任務
異步: 可以同時執行多個任務,提高了程序的執行效率
同步任務: 同步任務都在主線程上執行, 形成一個執行棧. 同步任務是依次執行的.
**異步任務:**JS的異步任務一般是通過回調函數來實現的, 在做某個任務的同時還可以處理其他任務
4. JS執行機制
首先判斷JS任務是同步任務, 還是異步任務. 同步任務會在主線程的執行棧中依次執行.
異步任務會提交給異步進程處理(setTimeout/ click事件等,此時異步進程也在執行相關的邏輯判斷).
? 滿足觸發條件后, 異步進程會將異步任務(回調函數)放到任務隊列(臨時進行存放的一個空間)里面去
? 如果有, 就拿到主線程中執行(立即性). 執行完之后再去任務隊列里面查找, 依次循環.
十四、正則表達式
1. 定義與作用
正則表達式是什么?
- 是用于匹配字符串中字符組合的模式
正則表達式有什么作用?
- 表單驗證(匹配)
- 過濾敏感詞(替換)
- 字符串中提取我們想要的部分(提取)
2. 判斷字符串是否符合規則:test()
用來查看正則表達式與指定的字符串是否匹配
reg.test(str) // 返回一個布爾值3. 檢索符合規則的字符串:exec()
- 在一個指定字符串中執行一個搜索匹配
- 如果匹配成功,exec() 方法返回一個數組,否則返回null
4. 元字符
- 是一些具有特殊含義的字符
- 可以極大提高了靈活性和 強大的匹配功能
1. 邊界符
- 提示字符所處的位置
| ^ | 匹配行首的文本(以誰開始) |
| $ | 匹配行尾的文本(以誰結束) |
如果 ^ 和 $ 在一起,表示必須是精確匹配
2. 量詞
設定某個模式出現的次數
| * | >=0 |
| + | >=1 |
| ? | 1或者0 |
| {n} | =n |
| {n,} | >=n |
| {n,m} | >=n && <=m |
3. 字符類
[ ] 匹配字符集合
-
后面的字符串只要包含 abc 中任意一個字符,都返回 true
/[abc]/.test('baby') // true /[abc]/.test('cry') // true /[abc]/.test('die') // flase[ ]加上 - 連字符:表示一個范圍
/[abc]/.test('abc') // true /^[abc]$/.test('a') // true /^[abc]$/.test('abc') // false[ ] 里面加上 ^ 取反符號:匹配除了小寫字母以外的字符
==> [^...] 里面寫^表示取反, 不能是里面的任意一個字符. ==> /^xxx/ 如果寫到正則的最前面, 表示邊界符, 以什么開頭. 匹配除換行符之外的任何單個字符
/n./.test('an') // false /n./.test('na') // true /.n/.test('an') // true /.n/.test('ab+n') // true-
預定義:某些常見模式的簡寫方式
預定類說明 \d ==> [0-9] \D ==> [ ^ 0-9] \w [A-Za-z0-9_] \W [^A-Za-z0-9_] \s 匹配空格 \S 匹配非空格的字符
-
5. 修飾符
- i,正則匹配時字母不區分大小寫
- g,匹配所有滿足正則表達式的結果
- replace 替換
總結
- 上一篇: 自定义new Date()格式显示,适用
- 下一篇: 西门子S7-1200PLC控制3轴伺服程