web-API
Jonnzer Lv4

DOM

DOM :( Document Object Model 文档对象模型),是针对 HTML 和 XML 文档的一个 API 。
DOM 描绘了一个层次化的节点树,允许开发人员 增删改查 页面的某一部分。

attribute:getAttriubte 、 setAttribute 给 HTML 标签元素设置自定义属性
property : dom.style.width 、dom.className 给 HTML 标签的 JS 变量设置属性
而 attribute 和 property 的修改,都可能引起 DOM 重新渲染。建议用 property。

nodeName:元素的标签名
nodeType: 表明节点类型

DOM 是那种数据结构?

树型

DOM 操作的常用 API ?

获取 DOM 节点: getElementById 、getElementsByTagName 、 getElementByClassName 、 querySelectorAll

新增 、插入节点:
appendChild:用于向 childNodes 列表的末尾添加一个节点。添加节点后,childNodes 的新增节点、父节点、以前的最后一个节点的关系指针都会更新。 appendChild() 返回新增的节点

1
2
3
var returnNode = someNode.appendChild(newNode)
returnNode === newNode // true
someNode.lastChild === newNode // true

同时,如果 newNode 已经是文档中的一部分,那么页面呈现,将是该节点从原来的位置,转移到新的位置

获取子元素列表,获取父元素:
获取父元素: dom.parentNode
获取子元素列表: dom.childNodes (会把不同 nodeType 的元素 都弄在一起)

1
2
3
const childNodeFilter = Array.prototype.slice.call(div.childNods).filter((child) => {
return child.nodeType === 1 // 过滤只保留标签元素
})

删除子元素:
removeChild:

1
var beremovedTarget = dom.removeChild(dom.firstChild)
attr 和 property 的区别?
DOM 性能

DOM 操作昂贵,避免频繁的 DOM 操作
对 DOM 查询做缓存

1
2
3
4
5
6
7
8
9
10
11
// 不缓存 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 查询
}

将频繁操作改为一次性操作:
DocumentFragment 是一种轻量型文档(文档片段)。可以当作将要添加到 document 的节点仓库来使用。(临时区)
如果将 文档中的节点 添加到 文档片段中,就会从 文档树 移除该节点,也不会在浏览器看到该节点。
appendChild 或者 insertBefore 可以使 文档片段的节点 恢复到 文档树中。

1
2
3
4
5
6
7
8
9
10
11
const listNode = document.getElementById('list')

const frag = document.createDocumentFragment() // 文档片段 此时还没插入 DOM 结构中

for (let i = 0; i < 10; i++) {
let list = document.createElement('li')
list.innerHTML = 'list item ' + i
frag.appendChild(list)
}

listNode.appendChild(frag)

一次性插入多个 DOM 节点,考虑性能

BOM(浏览器对象模型)

navigator 识别浏览器的标准
history 对象保存上网的历史记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// navigator
const ua = navigator.userAgent
const isChorme = ua.indexOf('Chrome')
console.log(isChrome)

// screen
console.log(screen.width)
console.log(screen.height)

// history
history.go(-1) // 参数为负数则是 后退多少页
history.go(2) // 参数为正数则是 前进多少页

// 模拟浏览器前进后退
history.forward() // 前进
history.back() // 后退

history.length === 0 // 页面是否为用户新打开的

// location
window.location === document.location // true
location.href === location.toString()
// url: https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model/Introduction?q=1#%E4%BB%80%E4%B9%88%E6%98%AF_dom
console.log(location.href) // 页面完整 url https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model/Introduction?q=1#%E4%BB%80%E4%B9%88%E6%98%AF_dom
console.log(location.protocal) // https:
console.log(location.pathname) // /zh-CN/docs/Web/API/Document_Object_Model/Introduction
console.log(location.search) // '?q=1'
console.log(location.hash) // #%E4%BB%80%E4%B9%88%E6%98%AF_dom
如何识别浏览器的类型
查询 url 字符串参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 正则
var getUrlParam = function (name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return decodeURI(r[2]); return null;
}

console.log(getUrlParam('id'));

// 对象
function getQueryStringArgs() {
let args = {}
let key
let value
var qs = location.search.length > 0 ? location.search.substring(1) : ''
let arr = qs.length ? qs.split('&') : []
const length = arr.length
for (let i = 0; i < length; i++) {
let item = arr[i].split('=')
console.log(item)
key = decodeURIComponent(item[0])
value = decodeURIComponent(item[1])
key.length && args[key] = value
}
return args
}

console.log(getQueryStringArgs()['q'])

Ajax

知识点

XMLHttpRequest:
XMLHttpRequest(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。

readyState:

状态 描述
0 UNSENT 代理被创建,但尚未调用 open() 方法。
1 OPENED open() 方法已经被调用。
2 HEADERS_RECEIVED send() 方法已经被调用,并且头部和状态已经可获得。
3 LOADING 下载中;responseText 属性已经包含部分数据。
4 DONE 下载操作已完成。

状态码:( xhr.status )

  • 2XX: 表示成功处理请求,如 200
  • 3XX: 需要重定向,浏览器直接跳转,如 301 302 304
  • 4XX: 客户端请求错误,如 404 403
  • 5XX:服务器端错误

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

同源策略仅限浏览器

  • ajax 请求时,浏览器要求当前网页server 必须同源(安全)
  • 同源:协议、域名、端口,三者必须一致
    eg: 前端:http://a.com:8080/ , server: https://b.com/api/xxx

加载 img JS CSS 无视 同源策略:( img src \ link href \ script src )

  • img 可以做防盗链(服务器做)
  • img 可以做统计打点,使用第三方统计服务
  • link script 可使用 CDN CDN 一般是外链
  • script 可使用 JSONP

跨域:

  • 所有的跨域,都必须经过 server 端允许和配合
  • 未经 server 端允许就实现跨域,说明 浏览器 有漏洞,危险信号

JSONP:

  • 访问 https://imooc.com/,服务端一定返回一个 html 文件吗?
    不一定。服务器可以任意动态拼接数据返回,只要符合 html 格式要求
    同理于

  • script 跨域特性:
    script 可绕过跨域限制
    服务器可以任意动态拼接数据返回
    所以,script 就可以获得跨域的数据,只要服务端愿意返回
    一般 script 用在 JSONP ,都是动态创建

1
2
3
var script = document.createElement('script')
script.src = 'http://free.net/json/?callback=handleResponse'
document.body.insertBefore(script, document.body.firstChild)

下面的代理,服务器代理返回了 obj 对象

1
2
3
4
5
6
// jsonp.js
const obj = {
x: 1,
y: 2
}
abc(obj)
1
2
3
4
5
6
<script>
window.abc = function(data) {
console.log(data)
}
</script>
<script src="http://localhost:8002/jsonp.js?username=xxx&callback=abc"></script>

jQuery 实现 JSONP:

1
2
3
4
5
6
7
8
$.ajax({
url: 'http://localhost:8082/x-orgin.json',
dataType: 'jsonp',
jsonpCallback: 'callback',
success: function(data) {
console.log(data)
}
})

CORS:(服务器支持)

  • 服务器设置 http header
    如果设置了,ajax 就可以直接跨域请求
    1
    2
    3
    4
    5
    6
    7
    response.setHeader('Access-Control-Allow-Origin', 'http://localhost:8000') // 不建议 *
    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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// get 请求
const xhr = new XMLHttpRequest()
xhr.open("GET", "/api", true) // true 是异步 false 是同步
xhr.onreadystatechange = function() {
// 异步模块
if (xhr.readyState === 4) {
if (xhr.status === 200) {
alert(xhr.reponseText)
}
} else {
console.log('其他情况')
}
}
xhr.send(null) // XMLHttpRequest.send() 方法接受一个可选的参数,其作为请求主体;如果请求方法是 GET 或者 HEAD,则应将请求主体设置为 null。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// promise 版
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.error(err)
})
跨域的常见方式
  • JSONP
  • CORS

Fetch

MDN 定义
返回 promise
语法更简洁
不兼容 IE

存储

cookie 、localStorage 、 sessionStorage

cookie 本身用于浏览器 和 server 通讯,可以用 document.cookie 来修改

cookie 缺点:

  • API 修改方式太过蹩脚
  • 存储大小 最大 4KB
  • http 请求时需要发送到服务端,增加请求数据量
localStorage

HTML5 专门为存储 设计,最大可存 5M
API 简单易用 getItem setItem
不会随着 http 请求,被发送出去
永久存储

sessionStorage

HTML5 专门为存储 设计,最大可存 5M
API 简单易用 getItem setItem
不会随着 http 请求,被发送出去
只存储在当前会话,关闭标签页则清空

HTTP

开发界面,调用后端接口,提交 获取数据 - http 协议

review:

http 常见的状态码有哪些
  • 归类:
    1XX 服务器收到请求
    2XX 请求成功 如200
    3XX 重定向 如 302
    4XX 客户端错误 如 404
    5XX 服务端错误 如 500

  • 常见的:
    200 成功
    301 永久重定向 ( 配合 Response Headers 的 location 字段 ,浏览器自动处理):域名到期 ,下次自动重定向到新域名 结合 百度第一次打开其他网站来看 NetWork
    302 临时重定向 ( 配合 Response Headers 的 location 字段 ,浏览器自动处理)
    304 资源未被修改 资源请求过,已缓存下来,在服务器端也认为是最新的,没必要再请求
    404 资源未找到
    403 没权限
    500 服务器错误
    504 网关超时

http 常见的 header 有哪些?
  • Request Headers:
    Accept 浏览器可接收的数据格式
    Accept-Encoding 浏览器可接收的压缩算法 ,如 gzip
    Accept-language 浏览器接收语言
    Connection: kee-alive 一次 TCP 连接重复使用
    Cookie
    Host: 请求的域名
    User-Agent 浏览器信息
    Content-type 发送数据的格式 如 application/json

  • Response Headers:
    Content-type 返回数据的格式 如 application/json
    Content-length 返回数据的大小 多少字节
    Content-Encoding 返回数据的压缩算法
    cross-origin-resource-policy: cross-origin

  • 自定义 Header:用于验证特殊接口

  • 缓存类的 Headers:
    Cache-Control
    Expires
    Last-Modified
    If-Modified-Since
    Etag
    If-None-Match

什么是 Restful API?
  • http methods:
    传统的:get 获取 服务器数据 ,post 提交数据到 服务器
    现在的:get 获取数据 ,post 新建数据, patch / put 更新数据, delete 删除数据

传统的 API 设计:把每个 url 当做一个功能 ( 重要 )

  • Restful API :
    是 一种新的 API 设计方法( 早已推广使用 )
    把每个 url 当作一个唯一的资源 ( 重要 )
如何设计一个资源?

尽量不用 url 参数
传统 API 设计: /api/list?pageIndex=2
Restful API 设计:/api/list/2

  • 用 method 表示操作类型
    传统 API :
    post : /api/create-blog
    post : /api/update-blog?id=100
    get : /api/get-blog?id=100

  • Restful:
    post: /api/blog
    patch: /api/blog/100
    get: /api/blog/100

描述一下 http 的缓存机制( 重要 )
  • 关于缓存,为什么需要缓存
    网络请求 速度 和 不稳定( 地域或环境 ),已经成为目前计算机优秀 CPU 算力和 优秀渲染引擎的 短板,有必要进行缓存,减少请求的体积,让页面加载的更快。

  • 哪些资源需要缓存?
    静态资源:JS CSS Img( 哈希后缀 )
    可结合 打包工具 webpack 输出哈希

  • 缓存策略 ( 强制缓存 + 协商缓存 )
    强制缓存:
    Response Headers中,

Cache-Control:max-age=31536000 ( 单位是秒 ) 最大缓存一年
除了 max-age
还有 no-cache 指定 no-cache 或 max-age=0, must-revalidate 表示客户端可以缓存资源,每次使用缓存资源前都必须重新验证其有效性。这意味着每次都会发起 HTTP 请求,但当缓存内容仍有效时可以跳过 HTTP 响应体的下载。
no-store 缓存不应存储有关客户端请求或服务器响应的任何内容,即不使用任何缓存。
private 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。私有缓存可以缓存响应内容,比如:对应用户的本地浏览器。
public 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存,即使是通常不可缓存的内容。(例如:1.该响应没有max-age指令或Expires消息头;2. 该响应对应的请求方法是 POST 。)对于应用程序中不会改变的文件,你通常可以在发送响应头前添加积极缓存。这包括例如由应用程序提供的静态文件,例如图像,CSS文件和JavaScript文件。

初次请求,返回资源和 Cache-Control。

如果还在 Cache-Control 控制时间内,浏览器再次请求,会直接从 本地缓存 中请求,返回资源。

缓存失效,会再次请求服务端,返回资源 和 Cache-Control。

Expires: 也是控制缓存过期,后 被 Cache-control代替

MDN Cache-Control

(1)协商缓存:
服务端 缓存策略
服务端 判断客户端资源 ,是否和服务端资源一样
一致则返回 304 ,否则返回 200 和 最新资源

浏览器初次请求服务端,返回资源和资源标识。
再次请求,带着资源标识,返回304,或返回资源和新的资源标识。

(2)资源标识:
在 Response Headers 中,有两种:Last-Modified 和 Etag

优先使用 Etag 精确到 毫秒

Last-Modified 资源的最后修改时间 精确到 秒

初次请求,返回资源和 Last-Modified
再次请求,Req Headers 带着 If-Modified-Since,
服务器判断是不是一样,304,否则返回资源 和 新的 Last-Modified

Etag 资源的唯一标识 ( 一个字符串,类似人类的指纹 )
初次请求,返回资源和 Etag
再次请求,Req Headers 带着 If-None-Match,
服务器判断是不是一样,304,否则返回资源 和 新的 Etag

Http缓存

  • 刷新操作方式,对缓存的影响
    正常操作:地址栏输入 url,跳转链接,前进后退等:
    强制缓存有效,协商缓存有效

手动刷新:F5 点击刷新 右击菜单刷新
强制缓存失效,协商缓存有效

强制刷新:Ctrl + F5
强制缓存失效,协商缓存失效

  • 本文标题:web-API
  • 本文作者:Jonnzer
  • 创建时间:2021-04-01 17:20:35
  • 本文链接:https://jonnzer.github.io/2021/04/01/JS/web-API/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论