DOM
DOM
- Document Object Model
- 是JS能识别的html结构
- 树结构
DOM节点操作
- 获取DOM节点
- getElementById
- getElementsByTagName
- getElementsByClassName
- querySelectorAll
- property
- style
- className
- nodeName
- nodeType
- attribute
- getAttribute
- setAttribute
- property和attribute区别
- property修改对象属性,不会体现到html结构中
- attr修改html属性,会改变html结构
- 两者都可能引起DOM重新渲染
DOM结构操作
- 新增/插入节点
- createElement
- appendChild
- 获取子元素列表,获取父元素
- parentNode
- childNodes
- 删除节点
- removeChild
DOM性能
- DOM操作非常“昂贵”,避免频繁的DOM操作
- 对DOM查询做缓存
// 不缓存 DOM 查询结果
for (let = 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 查询
}
将频繁操作改为一次性操作(插入多个标签时,先插入 Fragment 然后再统一插入DOM)
const listNode = document.getElementById('list')
// 创建一个文档片段,此时还没有插入到 DOM 树中
const frag = document.createDocumentFragment()
// 执行插入
for(let x = 0; x < 10; x++) {
const li = document.createElement("li")
li.innerHTML = "List item " + x
frag.appendChild(li)
}
// 都完成之后,再插入到 DOM 树中
listNode.appendChild(frag)
事件
事件代理
- 就是利用事件冒泡或者事件捕获机制,把一系列内层元素事件绑定到外层元素
- 有点
- 使代码简洁
- 减少浏览器内存占用
- 但是,不要滥用
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 div3 = document.getElementById("div3");
bindEvent(div3, "click", "a", function (event) { // 注意,这里不可用箭头函数
event.preventDefault();
alert(this.innerHTML)
})
Ajax
XMLHttpRequest
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) {
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.log(err))
跨域
什么是跨域
- ajax请求时,浏览器要求当前网页必须和server同源
- 同源:协议、域名、端口,三者必须一致
加载图片,css,js可无视同源策略
跨域
- 所有的跨域,都必须经过server端允许
- 未经server端允许就实现跨域,说明浏览器有漏洞
JSONP
- script可绕过跨域
- 服务器可任意动态拼接数据返回
- 所以,script就可以获得跨域的数据,只要服务器端愿意返回
CORS
- 服务器端设置http header
存储
cookie
- 用于浏览器和server通讯
- 被借用到本地存储来
- 可用
document.cookie=""
来修改 - 缺点
- 存储太小,最大4KB
- http请求时,会发送到服务端,增加请求数据量
- 只能用
document.cookie
来修改,太过简陋 localStorage与sessionStorage
- html5专门为存储设计的,最大可存5M
- API简单易用
- 不会随着http请求发送出去
- 区别
- localStorage数据永久存储,除非手动或者代码删除
- sessionStorage数据只存在于当前会话,浏览器关闭则清空