日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

(九)JS-WEB-API(DOM、BOM、事件、Ajax、存储)【每个工程师必须熟练掌握的技能】

發布時間:2023/12/31 javascript 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (九)JS-WEB-API(DOM、BOM、事件、Ajax、存储)【每个工程师必须熟练掌握的技能】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JS-WEB-API

  • 提問
    • DOM
    • BOM
    • 事件
    • Ajax
    • 存儲
  • 從JS基礎知識到JS-WEB-API
    • JS基礎知識
    • JS-WEB-API
      • DOM(Document Object Model)
        • DOM本質
        • DOM節點操作
        • DOM結構操作
        • DOM性能
      • BOM(Browser Object Model)
      • 事件
      • Ajax
        • XMLHttpRequest
        • 狀態碼
          • xhr.readyState
          • xhr.status
        • 跨域:同源策略,跨域解決方案
        • 手寫一個簡易的Ajax
        • 實際項目中ajax的常用插件
      • 存儲
        • 描述cookie localStorage sessionStorage的區別

提問

DOM

  • DOM是哪種數據結構
    樹(DOM樹)
  • DOM操作的常用API
    DOM節點操作、DOM結構操作
  • attr和property的區別
  • 一次性插入多個DOM節點,考慮性能

BOM

  • 如何識別瀏覽器的類型
  • 分析拆解url的各個部分

事件

  • 編寫一個通用的事件監聽函數
  • 描述事件冒泡的流程
  • 無限下拉的圖片列表,如何監聽每個圖片的點擊

Ajax

  • 手寫一個簡易的ajax
  • 跨域的常用實現方式

存儲

  • 描述cookie localStorage sessionStorage的區別

從JS基礎知識到JS-WEB-API

  • JS基礎知識,規定語法(ECMA 262標準)
  • JS-WEB-API,網頁操作的API(W3C標準)
  • 前者是后者的基礎,兩者結合才能真正實際應用

JS基礎知識

  • 變量的類型和計算
  • 原型和原型鏈
  • 作用域和閉包
  • 異步

JS-WEB-API

  • DOM
  • BOM
  • 事件綁定
  • ajax
  • 存儲

DOM(Document Object Model)

  • Vue和React框架應用廣泛,封裝了DOM操作
  • 但DOM操作一直都會是前端工程師的基礎,必備知識
  • 只會Vue不懂DOM操作的前端程序員,不會長久

DOM本質

html語言,html文件解析出來的一棵樹

DOM節點操作

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>dom 演示</title><style>.container {border: 1px solid #ccc;}.red {color: red;}</style></head><body><div id="div1" class="container"><p id="p1">一段文字 1</p><p>一段文字 2</p><p>一段文字 3</p></div><div id="div2"><img src="https://img3.mukewang.com/5a9fc8070001a82402060220-100-100.jpg"/></div><ul id="list"></ul><script src="./dom-3.js"></script></body> </html>
  • 獲取DOM節點
const div1 = document.getElementById('div1') //元素 console.log('div1', div1)const divList = document.getElementsByTagName('div') // 集合 console.log('divList.length', divList.length) console.log('divList[1]', divList[1])const containerList = document.getElementsByClassName('container') // 集合 console.log('containerList.length', containerList.length) console.log('containerList[1]', containerList[1])const pList = document.querySelectorAll('p') // 集合 console.log('pList', pList)
  • attribute
    通過修改或者獲取js的屬性來改變頁面樣式、頁面渲染結構的一種形式,Dom結構js變量的修改
const pList = document.querySelectorAll('p') const p1 = pList[0]// property 形式 p1.style.width = '100px' console.log( p1.style.width ) p1.className = 'red' console.log( p1.className ) console.log(p1.nodeName) console.log(p1.nodeType) // 1
  • property
    修改標簽的屬性,Dom結構節點屬性修改
// attribute const pList = document.querySelectorAll('p') const p1 = pList[0] p1.setAttribute('data-name', 'imooc') console.log( p1.getAttribute('data-name') ) p1.setAttribute('style', 'font-size: 50px;') console.log( p1.getAttribute('style') )
  • 總結
property:修改對象屬性,不會體現到html結構中 attribute:修改html屬性,會改變html結構 兩者都有可能引起DOM重新渲染 最好使用property

DOM結構操作

  • 新增/插入節點
const div1 = document.getElementById('div1') const div2 = document.getElementById('div2')// 新建節點 const newP = document.createElement('p') newP.innerHTML = 'this is newP' // 插入節點 div1.appendChild(newP)// 移動節點 const p1 = document.getElementById('p1') div2.appendChild(p1)
  • 獲取子元素列表,獲取父元素
// 獲取父元素 console.log( p1.parentNode )// 獲取子元素列表 const div1ChildNodes = div1.childNodes console.log( div1.childNodes )//還會含有text文本標簽,nodeType 等于3 const div1ChildNodesP = Array.prototype.slice.call(div1.childNodes).filter(child => {if (child.nodeType === 1) {return true}return false }) console.log('div1ChildNodesP', div1ChildNodesP)
  • 刪除子元素
div1.removeChild( div1ChildNodesP[0] )

DOM性能

  • DOM操作非常“昂貴”,避免頻繁的DOM操作
  • 對DOM查詢做緩存
//不緩存 DOM 查詢結果 for (let i = 0; i < document.getElementsByTagName('p').length; i++){//每次循環,都會計算length,頻繁進行DOM查詢 } //緩存 DOM 查詢結果 const pList = document.getElementsByTagName('p') const length = pList.length for (let i = 0; i < length ; i++){//緩存length,只進行一次DOM查詢 }
  • 將頻繁操作改為一次性操作,一次性插入多個節點,考慮性能
const list = document.getElementById('list')// 創建一個文檔片段,此時還沒有插入到 DOM 結構中 const frag = document.createDocumentFragment()for (let i = 0; i < 20; i++) {const li = document.createElement('li')li.innerHTML = `List item ${i}`// 先插入文檔片段中frag.appendChild(li) }// 都完成之后,再統一插入到 DOM 結構中 list.appendChild(frag)console.log(list)

BOM(Browser Object Model)

  • navigator(瀏覽器信息)
const ua = navigator.userAgent const isChrome = ua.indexOf('Chrome') console.log(isChrome)
  • screen(屏幕信息,例如寬度高度等)
console.log(screen.width) console.log(screen.height)
  • location(地址信息)
console.log(location.href) console.log(location.protocol) //http:或https: console.log(location.pathname) console.log(location.search) console.log(location.hash)
  • history(前進后退信息)
history.back() history.forward()

事件

  • 事件綁定
const btn = document.getElementById('btn1') btn.addEventListener('click', event => {console.log('clicked') }) //通用的綁定函數 function bindEvent(elem,type,fn){elem.addEventListener(type,fn) } const a= document.getElementById('link1') bindEvent(a, 'click', (e)=> {// console.log(event.target) // 獲取觸發的元素event.preventDefault() // 阻止默認行為alert('clicked') })
  • 事件冒泡
    從下向上進行冒泡
<body><div id="div1"><p id="p1">激活</p><p id="p2">取消</p><p id="p3">取消</p><p id="p4">取消</p></div><div id="div2"><p id="p5">取消</p><p id="p6">取消</p></div> </body>const p1 = document.getElementById('p1') const body = document.body bindEvent(p1,'click',e => {e.stopPropagation() //阻止冒泡,可以注釋這一行,來體會事件冒泡,沒有這一行的話會先彈激活,再彈取消,有這一行只彈激活alert('激活') }) bindEvent(body,'click',e => {alert('取消') })
  • 事件代理
    代碼簡潔、減少瀏覽器內存占用、但是不要濫用
<div id="div1"><a href="#">a1</a><a href="#">a2</a><a href="#">a3</a><a href="#">a4</a> </div> <button>點擊增加一個a標簽</button>const div1 = document.getElementById('div1') bindEvent(div1,'click',event => {event.preventDefault() // 阻止默認行為const target = event.targetif(target.nodeName === 'A'){alert(target.innerHTML)} }) <body><button id="btn1">一個按鈕</button><div id="div3"><a href="#">a1</a><br><a href="#">a2</a><br><a href="#">a3</a><br><a href="#">a4</a><br><button>加載更多...</button></div> </body> //通用的事件綁定函數,兼容事件綁定和事件代理 function bindEvent(elem, type, selector, fn) {if (fn == null) {fn = selectorselector = null}elem.addEventListener(type, event => {const target = event.targetif (selector) {// 代理綁定if (target.matches(selector)) {fn.call(target, event)}} else {// 普通綁定fn.call(target, event)}}) }// 普通綁定 const btn1 = document.getElementById('btn1') bindEvent(btn1, 'click', function (event) {// console.log(event.target) // 獲取觸發的元素event.preventDefault() // 阻止默認行為alert(this.innerHTML) })// 代理綁定 const div3 = document.getElementById('div3') bindEvent(div3, 'click', 'a', function (event) {event.preventDefault()alert(this.innerHTML) }) //描述事件冒泡的流程 基于DOM樹形結構 事件會順著觸發元素往上冒泡 應用場景:代理 //無限下拉的圖片列表,如何監聽每個圖片的點擊 事件代理 用e.target獲取觸發元素 用matches來判斷是否是觸發元素

Ajax

XMLHttpRequest

//get請求 const xhr = new XMLHttpRequest() xhr.open('GET', '/data/test.json', true) //true為異步,false為同步 xhr.onreadystatechange = function () {//這里的函數異步執行if (xhr.readyState === 4) {if (xhr.status === 200) {// console.log(// JSON.parse(xhr.responseText)// )alert(xhr.responseText)} else if (xhr.status === 404) {console.log('404 not found')}} } xhr.send(null)//post請求 const xhr = new XMLHttpRequest() xhr.open('POST', '/login', true) //true為異步,false為同步 xhr.onreadystatechange = function () {//這里的函數異步執行if (xhr.readyState === 4) {if (xhr.status === 200) {// console.log(// JSON.parse(xhr.responseText)// )alert(xhr.responseText)} else if (xhr.status === 404) {console.log('404 not found')}} } const postData = {name:"zhangsan",passsword:"xxx" ] xhr.send(JSON.stringify(postData))

狀態碼

xhr.readyState
  • 0-(未初始化)還沒有調用send()方法
  • 1-(載入)已調用send()方法,正在發送請求
  • 2-(載入完成)send()方法執行完成,已經接收到全部響應內容
  • 3-(交互)正在解析響應內容
  • 4-(完成)響應內容解析完成,可以再客戶端調用
xhr.status
  • 2xx-表示成功處理請求,如200
  • 3xx-需要重定向,瀏覽器直接跳轉,如301,302,304
  • 4xx-客戶端請求錯誤,如404,403
  • 5xx-服務器端錯誤

跨域:同源策略,跨域解決方案

  • 什么是跨域(同源策略)
//同源策略//1.ajax請求時,瀏覽器要求當前網頁和server必須同源(安全)//2.同源:協議、域名、端口,三者必須一致//3.前端:http://a.com:8080/;server:https://b.com/api/xxx(線上默認80端口) //加載圖片 css js 可無視同源策略//1.<img src=跨域的圖片地址 />//2.<link href=跨域的css地址 />//3.<script src=跨域的js地址></script> //加載圖片 css js 可無視同源策略//1.<img />可用于統計打點,可使用第三方統計服務//2.<link /><script />可使用CDN,CDN一般都是外域//3.<script>可實現JSONP //跨域//1.所有的跨域,都必須經過server端允許和配合//2.未經server端允許就實現跨域,說明瀏覽器有漏洞,危險信號
  • JSONP
//訪問https://imooc.com/,服務端一定返回一個html文件嗎? //服務器可以任意動態拼接數據返回,只要符合html格式要求 //同理于<script src="https://imooc.com/getData.js"> //<script>可繞過跨域限制 //服務器可以任意動態拼接數據返回 //所以,<script>就可以獲得跨域的數據,只要服務端愿意返回

jsonp.html

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>jsonp 演示</title></head><body><p>一段文字 1</p><script>window.abc = function (data) {//這是我們跨域得到的信息console.log(data)//{ name: 'xxx' }}</script><script src="http://localhost:8002/jsonp.js?username=xxx&callback=abc"></script></body> </html>

jsonp.js

abc({ name: 'xxx' } ) //jQuery實現jsonp $.ajax({url:'http://localhost:8882/x-origin.json',dataType:"jsonp",jsonpCallback:"callback",success:function(data){console.log(data);} });
  • CORS(服務端支持)- 服務器設置http header
//第二個參數填寫允許跨域的域名稱,不建議直接寫“*” response.setHeader("Access-Control-Allow-Origin","http://locaohost:8011") response.setHeader("Access-Control-Allow-Headers","X-Requested-With") response.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS") //接受跨域的cookie response.setHeader("Access-Control-Allow-Credentials","true")

手寫一個簡易的Ajax

function ajax(url,successFn) {const xhr = new XMLHttpRequest()xhr.open('GET', url, true)xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status === 200) {successFn(xhr.responseText)}}}xhr.send(null) } function ajax(url) {const p = new Promise((resolve, reject) => {const xhr = new XMLHttpRequest()xhr.open('GET', url, true)xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status === 200) {resolve(JSON.parse(xhr.responseText))} else if (xhr.status === 404 || xhr.status === 500) {reject(new Error('404 not found'))}}}xhr.send(null)})return p }const url = '/data/test.json' ajax(url) .then(res => console.log(res)) .catch(err => console.error(err))

實際項目中ajax的常用插件

  • $.ajax
  • fetch
  • axios

存儲

  • cookie
本身用于瀏覽器和server通訊 被“借用”到本地存儲來 可用document.cookie = '...'來修改 document.cookie = 'a=100;b=200;' document.cookie //a=100 document.cookie = 'b=200;' document.cookie //a=100; b=200 document.cookie = 'a=300;' document.cookie //b=200; a=300 document.cookie = 'd=400;' document.cookie //b=200; a=300;d=400; //cookie缺點 存儲大小,最大4KB http請求時需要發送到服務端,增加請求數據量 只能用document.cookie = '...'來修改,太過簡陋
  • localStorage和sessionStorage
HTML5專門為存儲而設計,最大可存5M API簡單易用setItem,getItem 不會隨著http請求被發送出去 localStorage數據會永久存儲,除非代碼或手動刪除 sessionStorage數據只存在于當前會話,瀏覽器關閉則清空 一般用localStorage會更多一些

描述cookie localStorage sessionStorage的區別

  • 容量
  • API易用性
  • 是否跟隨http請求發送出去

總結

以上是生活随笔為你收集整理的(九)JS-WEB-API(DOM、BOM、事件、Ajax、存储)【每个工程师必须熟练掌握的技能】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。