JS Web API知识点
vue和React框架应用广泛,封装了DOM操作。但DOM操作一直都是前端必备基础。 JS基础知识,规定语法(ECMA 262标准) JS Web API,网页操作的API(W3C标准) DOM? BOM ? 事件绑定 ? ajax? 存储
DOM
问题:
DOM是哪种数据结构
DOM操作的常用API
attr和property的区别
一次性插入多个DOM节点,考虑性能
知识点:
DOM本质:从html语言解析出来的一个文档树
DOM节点操作
DOM结构操作
DOM性能
DOM节点操作
获取DOM节点
const div1 = document.getElementById('div1')
const divList = document.getElementsByTagName('div')
const containerList = document.getElementsByClassName('container')
const pList = document.querySelectorAll('p')
DOM节点的property
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)
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和attribute
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
题目
1.如何识别浏览器的类型
navigator.userAgent
2.分析拆解url各个部分
url组成:protocol :// hostname[:port] / path / [;parameters][?query]#fragment
location.href
location.protocol
location.pathname
location.search
location.hash
事件
题目
编写一个通用的事件监听函数
描述事件冒泡的流程
无限下拉的图片列表,如何监听每个图片的点击?
知识点
事件绑定 事件冒泡 事件代理
事件绑定
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 => {
e.preventDefault()
alert('clicked')
})
阻止冒泡
const p1 = document.getElementById('p1')
bindEvent(p1, 'click', event => {
event.stopPropagation()
console.log('激活')
})
const body = document.body
bindEvent(body, 'click', event => {
console.log('取消')
})
代理绑定
//改进 通用的事件监听函数
<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>
<script>
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)
})
</script>
描述事件冒泡的流程
基于DOM树形结构
事件会顺着触发元素向上冒泡
应用场景:代理
无限下拉图片列表,如何监听每个图片的点击
事件代理
用e.target获取触发元素
用matche来判断是否是触发元素
Ajax
题目
手写一个简易的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('GET', "/login", false)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
alert(xhr.responseText)
}
}
}
const postData = {
userName: 'zhangsan',
password: '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-服务端错误
跨域
跨域的实现方式
JOSNP
CORS
同源策略
ajax请求时,浏览器要求当前网页和server必须同源(安全)
同源:协议、域名、端口,三者必须一致
比如,前端:http://a.com:8080; server:https://b.com/api是不同源的
注意,此处针对浏览器。服务器仍可以向另一个服务器发送请求
加载图片css js可无视同源策略
<img src=跨域图片地址/>
<link href=跨域css地址/>
<script src=跨域js地址></script>
<img/>可用于统计打点,可使用第三方统计服务
<link /><script>可使用CDN,CDN一般都是外域
<script>可实现JSONP
所有的跨域,都必须进过server端允许配合
未经server端允许就实现的跨域,说明浏览器有漏洞
JSONP
了解实现原理
<script>可绕过跨域限制
服务器可以任意动态拼接数据返回
所以,<script>就可以获得跨域数据,只要服务端愿意返回
$.ajax({
url:'http://localhost:8882/x.json',
dataType:'jsonp'.
jsonpCallback:'callback',
success:function(data){
console.log(data)
}
})
CORS-服务器设置http header(通过服务端实现跨域,了解)
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))
Cookie
本地和服务端通讯,但被“借用”到本地存储来
最初的设计并不是本地存储,而是服务端通讯
可用document.cookie='...'来修改
cookie的缺点
存储大小,最大4kb
http请求时需要发送到服务端,增加请求数据量(每次http请求都会带上cookie)
只能用document.cookie='...'来修改,太过简陋
sessionStorage和localStorage
HTML5专门为存储而设计,最大可存5M
API简单易用 setItem getItem
不会随着http请求被发送出去
localStorage数据会永久存储,除非代码或手动删除
sessionStorage数据只存在于当前会话,浏览器关闭则清空
一般用localStorage会更多一些
localStorage.setItem('a',100)
localStorage.getItem('a')
描述cookie localStorage sessionStorage区别
容量
API易用性
是否跟随http请求发送出去
|