JS-WEB-API
- 提问
-
- 从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
事件
- 编写一个通用的事件监听函数
- 描述事件冒泡的流程
- 无限下拉的图片列表,如何监听每个图片的点击
Ajax
存储
- 描述cookie localStorage sessionStorage的区别
从JS基础知识到JS-WEB-API
- JS基础知识,规定语法(ECMA 262标准)
- JS-WEB-API,网页操作的API(W3C标准)
- 前者是后者的基础,两者结合才能真正实际应用
JS基础知识
- 变量的类型和计算
- 原型和原型链
- 作用域和闭包
- 异步
JS-WEB-API
DOM(Document Object Model)
- Vue和React框架应用广泛,封装了DOM操作
- 但DOM操作一直都会是前端工程师的基础,必备知识
- 只会Vue不懂DOM操作的前端程序员,不会长久
DOM本质
html语言,html文件解析出来的一棵树
![(九)JS-WEB-API(DOM、BOM、事件、Ajax、存储)【每个工程师必须熟练掌握的技能】_第1张图片](http://img.e-com-net.com/image/info8/69eb11a99447496a92cc3c107c3e23e8.jpg)
![(九)JS-WEB-API(DOM、BOM、事件、Ajax、存储)【每个工程师必须熟练掌握的技能】_第2张图片](http://img.e-com-net.com/image/info8/c63efeb8c0f94a8798a3fba298ce4d92.jpg)
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>
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]
p1.style.width = '100px'
console.log( p1.style.width )
p1.className = 'red'
console.log( p1.className )
console.log(p1.nodeName)
console.log(p1.nodeType)
- property
修改标签的属性,Dom结构节点属性修改
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 )
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查询做缓存
for (let i = 0; i < document.getElementsByTagName('p').length; i++){
}
const pList = document.getElementsByTagName('p')
const length = pList.length
for (let i = 0; i < length ; i++){
}
- 将频繁操作改为一次性操作,一次性插入多个节点,考虑性能
const list = document.getElementById('list')
const frag = document.createDocumentFragment()
for (let i = 0; i < 20; i++) {
const li = document.createElement('li')
li.innerHTML = `List item ${
i}`
frag.appendChild(li)
}
list.appendChild(frag)
console.log(list)
BOM(Browser Object Model)
const ua = navigator.userAgent
const isChrome = ua.indexOf('Chrome')
console.log(isChrome)
console.log(screen.width)
console.log(screen.height)
console.log(location.href)
console.log(location.protocol)
console.log(location.pathname)
console.log(location.search)
console.log(location.hash)
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)=> {
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.target
if(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 = selector
selector = null
}
elem.addEventListener(type, event => {
const target = event.target
if (selector) {
if (target.matches(selector)) {
fn.call(target, event)
}
} else {
fn.call(target, event)
}
})
}
const btn1 = document.getElementById('btn1')
bindEvent(btn1, 'click', function (event) {
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
const xhr = new XMLHttpRequest()
xhr.open('GET', '/data/test.json', true)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
alert(xhr.responseText)
} else if (xhr.status === 404) {
console.log('404 not found')
}
}
}
xhr.send(null)
const xhr = new XMLHttpRequest()
xhr.open('POST', '/login', true)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
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-服务器端错误
跨域:同源策略,跨域解决方案