WEB API

DOM

DOM 操作的常用 API

  1. getElementById:根据 ID 获取元素;
  2. getElementsByClassName:根据 className 获取元素集合;
  3. getElementsByTagName:根据标签名获取元素集合;
  4. querySelector:根据 CSS 选择器获取匹配的第一个元素;
  5. querySelectorAll:根据 CSS 选择器获取匹配的所有元素;
  6. createElement:根据标签名创建元素;
  7. appendChild:添加、移动元素;
  8. removeChild:移除元素;

attr 和 prototype 的区别

  1. prototype 修改的是对象属性,不会体现在 HTML 结构中;
  2. attribute 修改的是 HTML 属性,会改变 HTML 结构;
  3. 两者都有可能引起 DOM 的重新渲染;
  4. 尽可能的使用 prototype;

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

  1. 对 DOM 查询进行缓存;
  2. 使用 createDocumentFragment 创建文档片段,将多次操作合并为一次;

window.onload 和 DOMContentLoaded 的区别

window.onload 是页面所有资源加载完成后触发;

DOMContentLoaded 是 DOM 渲染完成后触发,不含图片等资源的加载;

BOM

如何识别浏览器类型

navigator.userAgent

分析拆解 URL 的各个部分

  1. protocol:协议;
  2. host:域名;
  3. port:端口;
  4. pathname:路径;
  5. search:参数;
  6. hash:路径

将 URL 解析为 js 对象

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
// 循环分割法
function query() {
const result = {};
// 去除 ?号
const url = location.search.substr(1);
const search = url.split("&");

search.foEach((paramStr) => {
const temp = paramStr.split("=");
const key = temp[0];
const value = temp[1];
result[key] = value;
});

return result;
}

// URLSearchParams
function query() {
const result = {};
const search = new URLSearchParams(location.search);
search.forEach((val, key) => {
result[key] = val;
});

return result;
}

从输入 URL 到页面渲染的整个过程

  1. 查找缓存;
  2. DNS 解析,把域名解析成 IP 地址;
  3. 客户端根据 IP 地址向服务器发起 HTTP 请求;
  4. 服务器响应请求并返回数据;
  5. 根据 HTML 生成 DOM 树;
  6. 根据 CSS 生成 CSSOM;
  7. 将 DOM 和 CSSOM 整合成渲染树;
  8. 根据渲染树渲染页面;
  9. 遇到 script 脚本,停止渲染,优先加载并执行 script;
  10. 直到渲染树渲染完成;

事件绑定

编写通用的事件监听函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function bindEvent(ele, type, selector, fn) {
// fn 为 null,则说明只传递了 3 个参数,selector 就是回调函数
if (fn === null) {
fn = selector;
selector = null;
}
ele.addEventListener(type, (event) => {
// 获取触发事件的元素
const target = event.target;
// 有 selector 说明是代理绑定
if (selector) {
// Element.matches 判断元素是否是指定元素
// 参数必须是 TagName,返回值为 true/false
if (target.matches(selector)) {
fn.call(target, event);
}
// 没有 selector 说明是普通绑定
} else {
fn.call(target, event);
}
});
}

描述事件冒泡的流程

由触发事件的元素顺着 HTML 结构,依次在父元素上触发该事件,直到 body;

  1. event.stopProPagation() 阻止事件冒泡;
  2. event.preventDefault() 阻止默认行为;

无限下拉图片列表,如何监听每一项的点击

使用事件代理;

AJAX

手写简易 ajax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function ajax(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(xhr.responseText);
} else {
reject(xhr.responseText);
}
}
};
xhr.send(null);
});
}

跨域的常见方式

同源策略:协议、域名、端口号,三者必须一致,仅限浏览器;

img、CSS、JS 的 src 属性可以无视同源策略;

jsonp 跨域

  1. 前端使用自定义 callback 写好业务逻辑;
  2. 然后发送请求,并标注 callback 的名称;
  3. 后台以指定 callback 返回数据;
  4. 浏览器加载 script 后会自动执行预定义的 callback 函数
  5. 这样就实现了跨域;

举个例子🌰:

1
2
3
4
5
6
7
8
9
// 前台定义,后台调用
window.userInfo = function (data) {
console.log(data);
};

// 浏览器加载 script 后会执行 script 中的代码,从而自动运行 userInfo 函数
const script = document.createElement("script");
script.src = "./userInfo.js?callback=userInfo";
document.body.appendChild(script);
1
2
3
4
5
6
// 后台直接调用前台给定的函数来返回数据
userInfo({
name: '章三';
age: 20,
city: '北京'
})

cors 跨域

由后台设置

1
2
3
4
5
6
7
8
// 允许跨域的域名
response.setHeader("Access-Control-Origin", "xxx");
// 允许跨域的请求头
response.setHeader("Access-Control-Headers", "xxx");
// 允许跨域的方法
response.setHeader("Access-Control-Methods", "GEt,POST,PATCH,DELETE,OPTIONS");
// 接收跨域的 Cookies
response.setHeader("Access-Control-Allow-Credentials", "true");

存储

描述 cookie、localStorage、sessionStorage 的区别

  1. cookie:容量小,会随请求一起发送;
  2. sessionStorage:会话存储,容量大,浏览器关闭自动删除;
  3. localStorage:永久存储,容量大,除非手动删除,否则一直存在;

HTTP

常见的 HTTP 状态码

  1. 200:请求成功;
  2. 301:永久重定向;
  3. 302:临时重定向;
  4. 304:资源未改变;
  5. 403:没有权限;
  6. 404:资源未找到;
  7. 502:服务器内部错误;
  8. 504:网关超时;

HTTP 常见的 header

request header

  1. accept:客户端可接收的数据格式;
  2. accept-encoding:客户端支持的压缩算法;
  3. accept-language:客户端支持的语言列表;
  4. content-type:发送的数据格式;
  5. user-agent:客户端标识;
  6. connection: keep-alive:重用 TCP 请求;
  7. cookie:用户标识;

response header

  1. content-type:返回的数据格式;
  2. content-encoding:返回数据的压缩算法;
  3. content-length:返回的数据大小;
  4. etag:资源标识;
  5. last-modify:资源最后更新时间;

描述 HTTP 的缓存机制

  1. cache-control、expires 强制缓存;
  2. last-modified etag 协商缓存;

强制缓存

  1. 初次请求,服务器返回资源和 cache-control(由服务器端控制);
  2. max-age 设置缓存有效时间,单位秒;
  3. 在有效期内,再次请求会直接从本地缓存返回资源;
  4. 缓存失效,再次请求,返回资源和 cache-control;

cache-control 的参数

  • max-age:最大有效时间,单位秒;
  • no-cache:不使用强制缓存;
  • no-store:不使用缓存,也不允许服务器做缓存设置;
  • private:只允许最终用户缓存;
  • public:允许中间服务器缓存;

expires 也可以控制缓存过期时间;

协商缓存 / 对比缓存

是一种服务器缓存策略,服务器会判断客户端资源和服务器是否一致,一致返回 304,否则返回 200 和新的资源;

  1. 初次请求,返回资源和资源标识;
  2. 再次请求,携带资源标识;
  3. 对比资源标识,一致返回 304,否则返回最新资源和资源标识;

last-modified:资源最后的修改时间,客户端请求时携带 key 为 if-modified-since,值为 last-modified 的请求头;

etag:资源唯一标识,可以理解为 hash,客户端请求时携带 key 为 if-none-match,值为 etag 的请求头;

last-modified 和 etag 同时使用时:

  1. 优先使用 etag;
  2. last-modified 只能精确到秒,资源重复生成时,不够准确;
  3. etag 根据资源内容生成,内容不变则 etag 不变;

刷新方式对缓存的影响

  1. 正常载入,强制缓存有效,对比缓存有效;
  2. 手动刷新,强制缓存失效,对比缓存有效;
  3. 强制刷新,强制缓存失效,对比缓存失效;

什么是 Restful API

  • 传统 API,把每个 URL 当作一个功能;
  • Restful API,把每个 URL 当作一个资源的唯一标识;

使用指定的方法对资源进行增删改查:

  • GET,获取数据;
  • POST,新建数据;
  • PATCH,更新数据:
  • DELETE,删除数据

Git

  1. git clone xxx 克隆分支
  2. git add . 跟踪所有内容
  3. git commit -m 提交修改到缓冲区并附加提交信息
  4. git push 推送到远端
  5. git pull 从远端同步
  6. git merger 合并分支
  7. git checkout 回滚
  8. git checkout -b 分支名 创建分支并切换到该分支
  9. git checkout 分支名 切换分支
  10. git branch 查看分支
  11. git branch 分支名 创建分支
  12. git branch -d 分支名 删除分支
  13. git status 查看当前工作目录的状态
  14. git log 仓库提交历史
  15. git log -p 显示每次提交的内容差异
  16. git log -stat 显示每次提交的简略统计信息
  17. git stash 暂存工作区的更改
  18. git stash pop 恢复工作区的内容

常见性能优化

  1. 防抖、节流;
  2. 懒加载
  3. 减少资源体积,如压缩代码;
  4. 减少请求次数,合并代码,使用缓存;
  5. 使用更快的网络 CDN;
  6. CSS 放在 head,JS 放在 body 最下面;
  7. 尽早执行 js,监听 DOMContentLoaded;
  8. 对 DOM 查询进行缓存;
  9. 频繁操作 DOM,使用 Fragment 合并插入,减少 DOM 操作;