从JS基础知识到JS Web API
- JS基础知识,规定语法(ECMA 262标准)
- JS Web API,网页操作的API(W3C标准)
- 前者是后者的基础,两者结合才能真正实际应用
JS Web API
JS-Web-API-DOM
前言
- Vue 和 React框架应用广泛,封装了DOM操作
- 但 DOM 操作一直都会是前端工程师的基础,必备知识
- 只会Vue而不懂DOM操作的前端程序员,不会长久
DOM(Document Object Model)
DOM本质
- DOM本质是HTML语言在浏览器中解析出来的树形结构
DOM节点操作
- 获取DOM节点
- getElementById
const div1 = document.getElementById('div1')
- getElementsByTagName
const divList = document.getElementsByTagName('div')
- getElementsByClassName
const divList = document.getElementsByClassName('.container')
- querySelectorAll
const divList = document.querySelectorAll('p')
- DOM 节点的property 和 attribute 区别
- property
const p = document.querySeletorAll('p')[0]
p.style.width = '100px'
- attribute
const p = document.querySeletorAll('p')[0]
p.setAttribute('data-name','wchao')
p.getAttribute('data-name')
- 两者区别
<-- 以此dom为例子 -->
<input id='test' class='a b c' type='text' value="1234" />
- 体系不同:二者是属于两套系统的不同的东西,但其中的属性又有所重合,且attributes本身又是property中的一个属性。所以attribute的属性一般都可以通过property 的方式获取到。
- 来源不同:在Js 的世界中,对象是通过构造函数创建的,所以每个对象中都天生自带了许多属性(property), 而attribute则是我们在书写代码时设置的一些属性。
- 状态不同:状态这个描述可能不太准确,attribute是我们给这个标签设置的属性,类似于这个标签的默认或初始属性值;而property 是这个dom对象或标签现在的属性。以这个input为例,我们设置的初始value值为“1234”,若我们输入了其他值如:“abcd”,此时property: input.value 的值为“abcd”, attribute:input.attributes.value 的值仍为 "1234"。当然不是所以的属性是这样,比如 id, class,type等属性是始终保持一致的。
- 建议:尽量用 property 操作,因为property可能会在JS机制中,避免一些不必要的DOM渲染;但是attribute是修改HTML结构,一定会引起DOM结构的重新渲染,而DOM重新渲染是比较耗费性能的
DOM结构操作
document.createElement(eName);
parentNode.appendChild(newNode);
p1.parentNode
const children = [].slice .call(box.childNodes).filter((ele) => ele.nodeType === 1)
console.log(children)
parentNode.removeChild(node);
DOM性能
- DOM操作非常“昂贵”,避免频繁的DOM操作
- 对DOM查询做缓存
for(let i = 0; i<document.getElementsByTagName('p').length; i++){
}
const pList = document.getElementByTagName('p')
const length = pList.length
for(let i = 0; i < length; i++){
}
- 将频繁操作改为一次操作(createDocumentFragment)
const list = document.getElementById('list')
for(let i = 0; i < 10; i++){
const li = document.createElement('li')
li.innerHTML = `List item ${i}`
list.appendChild(li)
}
const list = document.getElementById('list')
const frag = document.creatDocumentFragment();
for(let i = 0; i < 10; i++){
const li = document.createElement('li')
li.innerHTML = `List item ${i}`
frag.appendChild(li)
}
list.appendChild(frag)
JS-Web-API-BOM
BOM(Browser Object Model)
navigator(浏览器的信息)
- 判断ua
navigator.userAgent(各个浏览器,为了兼容限制的网页,添加了很多别的浏览器的标识在其中,所以很难明显的判断浏览器是谁的浏览器。只能网上查找,他们各自的检测方案)
const ua = navigator.userAgent
console.log(ua)
const isChorme = ua.indexOf('Chorme')
console.log(isChorme)
screen (屏幕信息)
screen.width
screen.height
location (地址的信息)
location.href
location.protocol
location.host
location.pathname
location.search
location.hash
history
history.back()
history.forward()
history.go()
JS-Web-API-事件
事件绑定
function bindEvent(elem,type,fn){
elem.addEventListener(type,fn)
}
const btn1 = document.getElementById('btn1')
bindEvent(btn1,'click',event=>{
event.preventDefault()
console.log('click')
})
事件冒泡
事件代理
- 事件代理(Event Delegation),又称之为事件委托。是 JavaScript 中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好处是可以提高性能
- 可以大量节省内存占用,减少事件注册,比如在table上代理所有td的click事件就非常棒
- 可以实现当新增子对象时无需再次对其绑定
- 基于事件代理的通用绑定方法
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)
}
})
}
var ul = document.getElementById("ul");
bindEvent(ul,'click','li',event => {
console.log(li click)
})
JS-Web-API-Ajax
XMLHttpRequest
- 什么是
XMLHttpRequest
XMLHttpRequest
(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest
在 AJAX编程中被大量使用。
- 手写原生ajax(get请求)
const xhr = new XMLHttpRequest()
xhr.open('GET','./data/test.json',false)
xhr.onreadystatechange=functon(){
if(xhr,readyState == 4){
if(xhr.status==200){
alert(xhr.responseText)
}
}
}
xhr.send(null)
const xhr = new XMLHttpRequest()
xhr.open('POST','./data/test.json',true)
xhr.onreadystatechange=functon(){
if(xhr,readyState === 4){
if(xhr.status === 200){
alert(xhr.responseText)
}
}
}
const postData = {
userName:'zhangsan',
password:'xxx'
}
xhr.send(JSON.stringify(postData))
- xhr.readuState 状态
- 0:未初始化,还未调用send方法
- 1:载入,已调用send方法,正发送请求
- 2:载入完成,send方法执行完毕,已接收到全部响应内容
- 3:交互,正在解析响应内容
- 4:完成,响应内容解析完成,可以再客户端调用
- xhr.status 状态
- 2xx 表示成功处理请求,如200
- 3xx 需要重定向,浏览器直接跳转,如301 302 304
- 4xx 客户端请求错误,如404 403
- 5xx 服务器端错误,如500
跨域
- 什么是跨域(同源策略)
- 同源策略
- 常见跨域方法
- 同源策略(利用img标签,可用于统计打点,可使用第三方统计服务)
- JSONP —— 需要与服务端配合(只支持get请求)
- CORS ——服务器设置 http header * (支持所有类型请求)
- postMessage
- websocket
- Node js中间件代理
- nginx反向代理
JS-Web-API-存储
cookie
- 语法:
document.cookie = newCookie;
- 本身用于浏览器和server通讯
- 最早是被“借用”到本地存储
- 缺点
- 1.存储大小,最大4kb
- 2.http 请求时需要发送到服务端,增加请求数据量
- 3.只能用 document.cookie = '...' 来修改,太过简陋
localStorage 和 sessionStorage
- HTML5 专门为存储设计,大小为5M
- Api简单易用(setItem,getItem)
- 不会随着http请求被发送出去
- 二者区别
- localStorage 永久存储,除非代码或手动删除
- sessionStorage 数据只存在于当前会话,浏览器关闭则清空
- 一般用 localStorage 会更多一点