HTML 部分
结构
一个 HTML 文档的基本结构如下:
<!DOCTYPE html>
<html lang="en">
<head>
<!--页面的字符集-->
<meta charset="utf-8" />
<!--页面的头文件-->
<meta http-equiv="expires" content="31 Dec 2008" />
<!--页面的描述信息-->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!--用于SEO的描述信息-->
<meta name="description" content="..." />
<meta name="keywords" content="..." />
<meta name="author" content="..." />
<meta name="copyright" content="..." />
<!--页面的标题-->
<title>Document</title>
<!--页面的外部资源-->
<link rel="stylesheet" type="text/css" href="theme.css" />
<!--页面的样式信息-->
<style></style>
</head>
<body>
<!--客户端脚本-->
<script></script>
<!--客户端不支持脚本时的替代显示内容-->
<noscript>浏览器不支持JavaScript脚本时的说明文字</noscript>
</body>
</html>
标签
标签分类
根据闭合特征,标签分为闭合标签和非闭合标签。其中,闭合标签如<html></html>,非闭合标签如<br />。
根据换行特征,标签分为块级元素和行内元素。其中,块级元素独占一行,具有宽、高等盒模型相关的 CSS 属性,从上到下排布,块级元素宽度继承自父元素宽度,高度由元素本身内容决定;行内元素和其它行内元素同占一行,不能被直接被定义宽、高等盒模型相关的 CSS 属性,如margin属性和padding属性仅影响元素水平方向上的排布,行内元素宽度和高度均有元素本身内容决定。
新增标签
HTML5 中新增了如下标签:
<!--多媒体(视频和音频)-->
<video controls>
<source src="test.ogg" type="video/ogg" />
<source src="test.mp4" type="video/mpeg" />
浏览器不支持video标签
</video>
<audio controls>
<source src="test.ogg" type="audio/ogg" />
<source src="test.mp3" type="audio/mpeg" />
浏览器不支持audio标签
</audio>
<!--进度条-->
<progress value="22" max="100"></progress>
<!--画布-->
<canvas></canvas>
<!--语义化-->
<header>
<nav></nav>
</header>
<main>
<article></article>
<strong></strong>
</main>
<footer></footer>
存储
HTML5 中新增了Cookie和WebStorage(SeesionStorage和LocalStorage),它们的对比如下:
Cookie:在客户端和服务端之间来回传递,大小不超过 4KB。在所有同源窗口中共享,过期前均有效(有效期通过expires字段或max-age字段进行设置)。在控制台输入window.document.cookie,可以查看当前Cookie的值,其形式为由键值对组成的字符串,如name1:value1; name2:value2; ...。服务端通过set-cookie响应字段以设置Cookie;客户端通过cookie请求字段以发送Cookie。LocalStorage:仅存储在客户端,大小最大为 5MB。在所有同源窗口中共享,浏览器关闭后仍不失效。绑定在window.localStorage上。客户端通过window.localStorage.setItem()/getItem()/removeItem()/clear()来管理LocalStorage。SeesionStorage:仅存储在客户端,大小最大为 5MB。仅在当前窗口中有效,浏览器关闭后即失效。绑定在window.sessionStorage上。客户端通过window.sessionStorage.setItem()/getItem()/removeItem()/clear()来管理sessionStorage。
CSS 部分
属性
CSS3 中新增了如下属性:
- 盒模型类:
box-sizing等。 - 边框类:
border-radius、box-shadow等。 - 背景类:
background-size、background-origin等。 - 变换类:
transform等。 - 动画类:
animation等。
选择器
略。
盒模型
CSS3 中,将元素们看作一个个盒子,盒子包含外边距、边框、内边距和宽高成分。
CSS3 中的盒模型分为以下两种:
- 标准盒模型:
盒子 = 元素自身。 - 怪异/IE 盒模型:
盒子 = 边框 + 内边距 + 元素自身。
切换盒模型的方法如下:
.box {
box-sizing: content-box; /* 标准盒模型 */
box-sizing: border-box; /* 怪异盒模型 */
}
定位
CSS3 中包含以下几种定位:
.box {
position: static; /*静态*/
position: relative; /*相对*/
position: absolute; /*绝对*/
position: fixed; /*固定*/
position: sticky; /*粘性*/
}
BFC
BFC 是一个将元素内外隔开的容器,可用于解决 margin 塌陷(父子元素之间)和 margin 合并(兄弟元素之间)的问题。
触发 BFC 的方法如下:
.bfc {
/*1.overflow属性不为visible*/
overflow: auto;
overflow: scroll;
overflow: hidden;
/*2.float属性不为none*/
float: left;
float: right;
/*3.position属性为absolute或fixed*/
position: absolute;
position: fixed;
/*4.display属性为flex、inline-flex和inline-block等*/
display: flex;
display: inline-flex;
display: inline-block;
}
响应式布局
Flex 布局
请见此文。
Table 布局
略。
媒体查询
媒体查询是指根据某些属性设计多种样式方案的过程:
/*当页面宽度小于300px时有效*/
@media screen and (max-width: 300px) {
body {
background-color: lightblue;
}
}
常见问题
清除浮动
利用clear属性或通过触发 BFC 来清除浮动:
.clear {
clear: both;
overflow: auto;
overflow: hidden;
}
垂直居中
利用 Flex 布局、padding属性、margin属性和transform属性等可实现垂直居中。
JavaScript 部分
数据类型
JavaScript 中的数据类型划分如下:
- 基本类型:
Undefined、Null、Boolean、Number、String、Symbol。 - 引用类型:
Object。
使用typeof可以对数据的基本类型进行判断:
// 返回其基本类型
typeof undefined; // 'undefined'
typeof true; // 'boolean'
typeof 42; // 'number'
typeof 9007199254740992n; // "bigint"
typeof '42'; // 'string'
typeof Symbol(); // 'symbol'
typeof {}; // 'object'
typeof []; // 'object'
typeof new Map(); // 'object'
typeof new Set(); // 'object'
// null和函数例外
typeof null; // 'object'
typeof function () {}; // 'function'
使用toString可以获取数据的内部类型:
// 包装toString方法
function toString(obj) {
return Object.prototype.toString.call(obj);
}
// 内部类型判断
toString(null); // '[object Null]'
toString(undefined); // '[object Undefined]'
toString(true); // '[object Boolean]'
toString(42); // '[object Number]'
toString('42'); // '[object String]'
toString(Symbol()); // '[object Symbol]'
toString({}); // '[object Object]'
toString([]); // '[object Array]'
toString(new Map()); // '[object Map]'
toString(new Set()); // '[object Set]'
toString(new Date()); // '[object Date]'
toString(/regex-literal/i); // '[object RegExp]'
toString(function () {}); // '[object Function]'
作用域和执行上下文
- 请见此文。
原型链和继承
- 请见此文。
事件循环、宏任务和微任务
**事件循环(Event Loop)**是一种保证 JavaScript 单线程运行却不会阻塞的机制,它将任务分为以下 2 种:
- 同步任务:按顺序执行的任务。
- 异步任务:不按顺序、延迟一段时间才执行的任务。
同步任务和异步任务的执行流程如下:
- 如果遇到同步任务,则将其放入到主线程中执行;如果遇到异步任务,则将其放入 Event Table 中并注册相应的回调函数。
- 主线程中的同步任务的执行过程中,如果 Event Table 中有异步任务完成(如计时器计时完成),则将相应的回调函数放入 Event Queue 中。
- 当主线程中没有可执行的同步任务时,就会到 Event Queue 中寻找是否有可执行的回调函数,如果有,则执行。
异步任务又被进一步地分为以下 2 种:
- 宏任务(Macro Task):整体代码、
setTimeout、setInterval。 - 微任务(Micro Task):
Promise.then、process.nextTick。
宏任务和微任务的执行流程如下:
- 宏任务的回调函数会被放入宏任务的 Event Queue 中,微任务的回调函数会被放入微任务的 Event Queue 中。
- 当主线程中没有可执行的同步任务时,优先执行微任务的回调,再执行宏任务的回调。
无论如何,在同一轮事件循环中,异步任务晚于同步任务执行,而异步任务中宏任务晚于微任务执行。
另外,通过以上可知:
setTimeout(fn,0)的含义为:立即将fn放入 Event Queue 中,待主线程为空时执行。setInterval(fn,n)的含义为:每过n毫秒,将fn放入 Event Queue 中,待主线程为空时执行。
异步编程
- 请见此文。
常见问题
this 指向及其改变
事件委托、冒泡和捕获
请见此文。
函数防抖和节流
函数防抖是指函数在被调用后等待一定时间再执行回调,若函数在一定时间内又被调用,则重新计时。
// 利用定时器实现:
function debounce(func, delay) {
let timer;
return function (params) {
// 如果被重复调用,则重新计时
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func(params);
}, delay);
};
}
函数节流是指函数在一定时间内只能被调用一次,若函数在一定时间内被调用多次,则只有一次生效。
// 利用定时器实现:
function throttle(func, delay) {
let timer;
return function (params) {
if (timer) return;
timer = setTimeout(() => {
func(params);
}, delay);
};
}
// 利用时间戳实现:
function throttle(func, delay) {
let prev;
return function (params) {
// 设置当前时间
let now = new Date();
// 在单位时间过后被调用
if (!prev || now - prev > delay) {
func(params);
prev = now;
}
};
}
函数柯里化
请见此文。
Vue 框架
原理
响应式原理:为每个属性定义 setter/getter 和一个依赖收集器 dep,并在 getter 中收集依赖,在 setter 中更新依赖。每一个组件对应一个依赖 watcher。当 render 时,触发 getter 收集依赖;当数据更新时,遍历该属性的 dep 中的 watcher 们,通知其重新渲染组件。
vue-diff 原理:将 node 抽象成 vnode,更新时,不是直接将 vnode 转换成 node 并覆盖旧 node,而是对旧 vnode 树和新 vnode 树进行比较,且比较只会在同层级进行,不会跨层级比较。且两个 vnode 的 key 和 sel 相同才去比较它们
模板语法
常用指令:
v-once
v-show v-if v-for
v-bind v-model v-on
v-text v-html
自定义指令:
// 全局指令
Vue.directive('directive-name', {
bind() {}, // 绑定时
update() {}, // 值更新时
unbind() {}, // 解绑时
inserted(el, binding) {}, // 插入到父节点(DOM)时
componentUpdated() {}, // vnode更新时
});
// 局部指令
Vue.component('component-name', {
directives: {
'directive-name'() {},
},
});
组件
- 组件注册。
- 组件配置:
props、component、data、methods、watch、computed、filters、directives。 - 组件通信:
props和$emit。 - 组件生命周期。
- 组件复用:插槽、混入等。
过渡和动画
生态
VueRouter
- hash 模式:不会向服务端发送请求,hash 值变化时,会触发 hashChange 事件,并将 hash 值发生的变化记录下来。
- history 模式:利用 History 的 pushState 和 replaceState 方法改变 url,且不发送请求,如此一来抛弃了丑陋的#,但是不支持刷新,除非服务端支持(使所有请求指向同一个 html 文件)。
const router = new VueRouter({
mode: 'history | hash',
routes: [
{
path: '/user/:id',
name: 'User',
component: User,
meta: {},
beforeEnter(to, from, next) {},
},
],
beforeEach(to, from, next) {},
beforeResolve(to, from, next) {},
afterEach(to, from, next) {},
});
export default {
name: 'Component',
beforeRouteEnter(to, from, next) {},
beforeRouteUpdate(to, from, next) {},
beforeRouteLeave(to, from, next) {},
};
this.$router.push({
// =>'/user'
name: 'User',
// =>'/user?id=ke'
params: {
id: 'ke',
},
// =>'/user/ke'
query: {
id: 'ke',
},
});
this.$route.params;
this.$route.query;
Vuex
const store = new Vuex.Store({
// this.$store.state
state: {},
// 触发:this.$store.commit(mutationName,payload)
// 用于直接改变state,必须同步
mutations: {
mutationA(state, payload) {},
},
// 触发:this.$store.dispatch(actionName,payload)
// 可以异步
actions: {
async actionA(context, payload) {
// context.state
// context.commit(mutationName,payload)
// context.dispatch(actionName,payload)
await actionB();
},
},
});
常见问题
computed 和 watch
watch:不支持缓存,建立对数据的依赖,依赖变则触发操作。computed:支持缓存,间接建立对数据的依赖,依赖变则重新计算。
$nextTick
在数据更新后,DOM 不会立即更新。通过$nextTick可以获取更新后的 DOM:
this.$nextTick(() => {
const ref = this.$refs;
});
Vue3 的改进
最大的改变,使用 es6 中的 Proxy 来代替 Object.defineProperty,在目标对象之上架了一层拦截,代理的是对象而不是对象的属性。这样可以将原本对对象属性的操作变为对整个对象的操作,可以监听到对象属性的增删和数组长度的变化,还可以监听 Map,Set,WeakSet,WeakMap 等,同时实现了惰性监听,即不会再初始化的时候创建所有的 observer,而是会在用到的时候才去监听。
const targetWithProxy = new Proxy(target, {
get(target, key) {},
set(target, key, val) {},
});
前端工程化
Babel
@babel/core
@babel/traverse
@babel/polyfill
babel-loader
过程:
- 解析:词法分析,语法分析,获取 AST。
- 转换:遍历并转换 AST。
- 生成:将修改后的 AST 复原成代码。
Webpack
module.exports = {
mode: 'development',
entry: '',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
// 文件加载器
module: {
rules: [
{ test: /\.css/, use: ['style-loader', 'css-loader'] },
{ test: /\.js/, use: ['babel-loader'] },
],
},
// 其他作用
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'src', 'index.html'),
title: '首页',
}),
],
};
性能优化
可以从以下几个方面进行前端性能优化:
- 传输:使用 Webpack 合并资源,减少 HTTP 请求。使用 gzip 压缩传输内容。
- 缓存:利用 HTTP 强缓存和协商缓存,以及将离线数据缓存到 localStorage 中。
- 渲染:调整 HTML 文档顺序,如将样式表放在文档顶端,将脚本放在文档底端。
- 其它:慎用闭包,防止内存泄漏。尽量减少全局变量的定义。尽量避免对 DOM 和样式的直接操作。
网络和安全
从输入 URL 到页面显示的过程
从用户输入 URL 到页面显示这一期间,依次经历了以下流程:
- 通过 DNS 服务器将域名解析为 IP 地址(优先级为:浏览器缓存>系统缓存>路由器缓存>运营商缓存>根域名服务器>顶级域名服务器)。
- 客户端与服务端之间经过三次握手,建立 TCP 连接。
- 客户端发送 HTTP 请求至服务端。
- 服务端处理 HTTP 请求,并将响应结果返回至客户端。
- 客户端与服务端之间经过四次挥手,关闭 TCP 连接。
- 浏览器解析 HTML 文档,生成 DOM 和 CSSOM,并结合这两者构建渲染树。
- 浏览器基于构建好的渲染树,经过回流和重绘,完成页面的渲染和布局。
GET 与 POST 请求对比
GET 请求和 POST 请求的对比如下:
- 参数传递:GET 请求通过 URL,POST 请求通过请求体。
- 参数长度:GET 请求有,POST 请求无。
- 安全表现:GET 请求参数暴露在 URL 中,不如 POST 请求安全。
- 编码类型:GET 请求仅支持 URL 编码,POST 请求支持
application-xxx、x-www-form-urlencode和multiple/form-data等多种编码格式。 - 记录保留:GET 请求会被完整的保留在历史记录中,而 POST 请求不会被保留。
- 数据传输:两者本质上都是 TCP 链接,但 GET 请求产生一个 TCP 数据包(发送请求-返回 200 状态码和资源),POST 请求产生两个 TCP 数据包(发送请求头-返回 100 状态码-发送请求体-返回 200 状态码和资源)。
状态码
HTTP 中的状态码由三个十进制数字组成,其中,第一个数字定义了状态码的类型。
状态码的分类如下:
- 1xx:服务端处于临时响应状态,等待客户端的进一步请求。
- 2xx:服务端处理请求成功。
- 3xx:请求重定向。
- 4xx:客户端发出的请求存在问题。
- 5xx:服务端处理请求时内部发生错误。
常见的状态码及其解释如下:
- 101:服务端正在进行协议升级的请求,如将连接类型升级到 WebSocket。
- 200:服务端处理请求成功,并通知客户端缓存响应内容。
- 204:服务端处理请求成功,但客户端无需更新现有页面。
- 301:永久重定向,即客户端请求的资源已经被移动到了另一位置,搜索引擎会根据 Location 响应头进行修正。
- 302:临时重定向,即客户端请求的资源被暂时地移动到了另一位置,搜索引擎不会自动进行修正。
- 304:协商缓存,详情请见缓存机制相关内容。
- 400:请求存在语法错误。
- 403:服务端拒绝请求。
- 404:服务端找不到请求资源。
- 408:服务端等待请求超时。
- 500:服务端处理请求时抛出了错误。
- 505:服务端不支持请求中的 HTTP 协议版本。
缓存机制
为节约请求消耗与提高网站性能,浏览器会将请求到的资源缓存下来,以供后续直接复用。HTTP 中的缓存机制分为强缓存和协商缓存两种,相关介绍如下:
- 强缓存:借助
Expires和Cache-Control这两个响应字段进行控制。其中,Expires为一个时间戳,表示缓存有效截止时间,如果为0则表示资源已经过期,当缓存失效时,将自动进入协商缓存阶段;Cache-Control为一系列键值对,包含有表示缓存有效时间的max-age属性和表示是否禁用强缓存的no-cache属性,结合max-age属性和Date响应字段,可以计算出强缓存的有效截止时间。Cache-Control的优先级高于Expires。 - 协商缓存:当强缓存过期或者请求头设置不使用强缓存时,将进入协商缓存阶段。协商缓存涉及两对字段:(1)
If-Modified-Since和Laset-Modified字段,如果请求头中携带了If-Modified-Since字段,则会请求服务端校验资源是否发生变化,如果有变化,服务端将正常返回当下最新的资源,并返回 200 状态码;如果没有变化,服务端将返回表示资源有效截止时间的Laset-Modified字段及 304 状态码,客户端收到后将使用缓存资源并更新缓存有效期。(2)If-None-Match和ETag字段,两者都是用于充当资源标识符的哈希值,通过对比请求头中的If-None-Match字段和响应头中的ETag字段,能够判断出协商缓存是否过期。
网络模型
OSI七层模型
应用层:HTTP/HTTPS
表示层
会话层
传输层:TCP/IP协议
网络层:IP协议
数据链路层:ARP协议
物理层:
TCP/IP五层模型
应用层、表示层、会话层被整合为应用层
TCP 和 UDP
TCP 面向连接,UDP 无连接。 TCP 可靠,UDP 不可靠。 TCP 保证信息完整,UDP 保证信息实时。 TCP 一对一,UDP 一对多。
TCP 三次握手:
- 客户端发送 SYN。
- 服务端发送 ACK 和 SYN。
- 客户端发送 ACK。
TCP 四次挥手:
- 客户端发送 FIN。(客户端申请关闭自己)
- 服务端发送 ACK。(然后等服务端发送完)
- 服务端发送 FIN。(服务端申请关闭自己)
- 客户端发送 ACK。
HTTP 和 HTTPS 协议对比
HTTP 各版本区别:
HTTP/1.0默认不开启长连接,HTTP/1.1默认开启
HTTP/1.1可以只发送header
HTTP/2.0不懂
报文格式:
# 请求
GET /baidu.com HTTP/1.1
header1: value1
header2: value2
connection: keep-alive 建立长连接
body
# 响应
HTTP/1.1 200 OK
header1: value1
header2: value2
body
状态码:
1xx 临时响应,请求继续操作
100 等待继续操作
101 要求切换协议
2xx 成功
200 成功
3xx 重定向
301 永久移动
302 临时移动
304 未修改,使用缓存
305 使用代理
4xx 请求错误
400 请求错误
404 无资源
5xx 服务器错误
500
HTTP 和 HTTPS 区别:
# 区别
安全性 http明文传输,https需要向CA申请证书,且有TLS/SSL加密协议
端口 http用80端口,https用443端口
# TLS/SSL
TLS是SSL的升级版
1. 客户端向服务端发起https请求,连接到服务端的443端口
2. 服务端将自己的公钥和证书发送给客户端,客户端验证证书的合法性,如果合法,生成密钥,并使用公钥来加密密钥
3. 客户端再次发起https请求,将加密后的密钥发送给服务端,服务端收到后,用私钥解密,获取到密钥
4. 服务端用密钥加密数据,并把数据发送给客户端,客户端用密钥解密,得到数据
GET 和 POST 请求,简单请求和复杂请求
GET 和 POST 请求:
参数传递 get通过url,post通过request body
参数长度限制 get有,post无
安全 get参数暴露在url中,不如post安全
编码 get只能url编码,post可多种(application/x-www-form-urlencode、multiple/form-data)
数据包 本质上都是TCP链接,无差别,get直接一次发送header和data,post先发送一次header,等待100后,再发送data
简单请求和复杂请求:
简单请求:
类型为 GET/POST/HEAD
content-type为text/plain、application/x-www-form-urlencoded、multipart/form-data三者之一
其他为复杂请求
跨域
1.cors
access-control-allow-origin
access-control-allow-methods
2.反向代理
proxy pass:
server {
listen 80;
server_name www.123.com;
location / {
proxy_pass http://127.0.0.1:8080;
index index.html index.htm index.jsp;
}
}
3.JSONP
缓存
客户端请求资源时(强刷新),会先获取该资源缓存的header信息,然后根据cache-control和expires来判断是否过期
若无过期,则直接从强缓存中获取资源信息
若已过期,则会向服务端发送请求
先通过if-none-match发送先前服务端发送过来的etag,服务端对etag进行比对
如果相同,则if-none-match为false,返回304,客户端使用协商缓存
如果不同,则if-none-match为false,返回200,客户端请求新资源
再通过if-modified-since发送先前服务端发送过来的last-modified,同理
CSRF 和 WXS
WebSocket
ajax 轮询:让浏览器每隔一段时间就发送一次请求,询问服务器是否有新消息。而利用 ajax 实时的从服务器获取内容,有可能导致大量的请求产生。 ajax 长轮询:采用阻塞模型。也就是说,当客户端发起连接后,如果服务器端内容没有更新,将响应至于挂起状态,一直不回复 response 给客户端,知道有内容更新,再返回响应。 WebSocket:是 HTML5 开始提供的一种浏览器与服务器进行全双工通讯的网络技术,属于应用层协议。它基于 TCP 传输协议,并复用 HTTP 的握手通道。一旦 web 服务器和客户端建立起 websocket 协议的通信连接,之后所有的通信都依靠这个专用连接进行。只需要经过一次 HTTP 请求,就可以做到源源不断的信息传送了。通过在请求首部中设置 Connection: Upgrade 来使用 websocket 协议。
数据结构与算法
计算机通识
Git
设计模式
观察者模式:被观察者管理观察者,观察者被动接受通知。 发布订阅模式:在观察者模式的基础上,添加了一个处理中枢。