面试校招基础
# 介绍
自己介绍
面试人介绍
面试结束后,提问给自己
# 项目
# 基础
# HTML基础
# 浏览器解析渲染页面
浏览器拿到响应文本 HTML 后,接下来介绍下浏览器渲染机制
浏览器解析渲染页面分为一下五个步骤:【DCJ渲布绘】
- 根据 HTML 解析出 DOM 树
- 根据 CSS 解析生成 CSS 规则树
- 结合 DOM 树和 CSS 规则树,生成渲染树
- 根据渲染树计算每一个节点的信息
- 根据计算好的信息绘制页面
# cookies,sessionStorage和localStorage区别
名称 | 生命期 | 大小限制 | 与服务器通信 |
---|---|---|---|
cookie | 一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 | 4KB | 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 |
sessionStorage | 仅在当前会话下有效,关闭页面或浏览器后被清除 | 5MB | 仅在浏览器中保存,不与服务器通信 |
localStorage | 除非被清除,否则永久保存 | 5MB | 仅在浏览器中保存,不与服务器通信 |
# HTTP
# http版本的比较
版本 | 内容 |
---|---|
http0.9 | 只允许客户端发送 GET 这一种请求;且不支持请求头,协议只支持纯文本;无状态性,每个访问独立处理,完成断开;无状态码 |
http1.0 | 解决 0.9 的缺点,增加 If-modify-since(last-modify)和 expires 缓存属性 |
http1.x | 增加 cache-control 和 If-none-match(etag)缓存属性 |
http2.0 | 采用二进制格式传输;多路复用;报头压缩;服务器推送 |
http3.0 | 采用 QUIC 协议,自定义连接机制;自定义重传机制;无阻塞的多路复用 |
# HTTP状态码
# 比较分类
序列 | 详情 |
---|---|
1XX(通知) | 代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束。101 Switching Protocols |
2XX(成功) | 200(成功)、201(服务器创建)、202(服务器接收未处理)、203(非授权信息)、204(未返回内容)、205(重置内容)、206(部分内容) |
3XX(重定向) | 301(永久移动)、302(临时移动)、303(查看其他位置)、304(未修改)、305(使用代理)、307(临时重定向) |
4XX(客户端错误) | 400(错误请求)、401(未授权)、403(禁止)、404(未找到)、405(方法禁用)、406(不接受)、407(需要代理授权) |
5XX(服务器错误) | 500(服务器异常)、501(尚未实施)、502(错误网关)、503(服务不可用)、504(网关超时)、505(HTTP 版本不受支持) |
总括:
- 1xx:指示信息–表示请求已接收,继续处理。
- 2xx:指示成功–表示请求已被成功接收、理解、接受。
- 3xx:指示重定向–要完成请求必须进行更进一步的操作。
- 4xx:指示客户端错误–请求有语法错误或请求无法实现。
- 5xx:指示服务器端错误–服务器未能实现合法的请求。
# 缓存分类
# 按协议分
协议层缓存和非 http 协议缓存
非协议层缓存:利用 meta
标签的 http-equiv
属性值 Expires
,set-cookie
。
协议层缓存:利用 http 协议头属性值设置;
# 按缓存分
强缓存和协商缓存
强缓存:利用 cache-control 和 expires 设置,直接返回一个过期时间,所以在缓存期间不请求,If-modify-since; 协商缓存:响应头返回 etag 或 last-modified 的哈希值,第二次请求头 If-none-match 或 IF-modify-since 携带上次哈希值,一致则返回 304。
类型 | 特性 |
---|---|
强缓存 | 通过 If-modify-since(last-modify)、expires 和 cache-control 设置,属性值是时间,所以在时间内不用请求 |
协商缓存 | 通过 If-none-match(etag)设置,etag 属性是哈希值,所以要请求和服务器值对比 |
# 缓存比较
强制缓存的优先级高于协商缓存,当执行强制缓存时,如若缓存命中,则直接使用缓存数据库数据,不在进行缓存协商。
协商缓存对比: etag 优先级高于 last-modified; etag 精度高,last-modified 精度是 s,1s 内 etag 修改多少次都会被记录; last-modified 性能好,etag 要得到 hash 值。
如果不是强制刷新,而且请求头带上了if-modified-since和if-none-match两个字段,则先判断etag,再判断last-modified。
# 校验过期机制
- 校验是否过期: Expires, Cache-Control(max-age)
- 协议Etag头信息校验; Etag
- 协议中Last-Modified头信息校验;Last-Modified
# CSS基础
# 布局相关设置【PDFOZ】
# display的设置
单位 | 描述 |
---|---|
none | 元素不显示,并从文档流中移除。 |
block | 块类型。默认宽度为父元素宽度,可设置宽高,换行显示。 |
inline | 行内元素类型。默认宽度为内容宽度,不可设置宽高,同行显示。 |
inline-block | 默认宽度为内容宽度,可以设置宽高,同行显示。 |
inherit | 规定应该从父元素继承 display 属性的值。 |
table | 此元素会作为块级表格来显示。表格显示; |
list-item | 象块类型元素一样显示,并添加样式列表标记。项目列表; |
/*==display 显示属性(div与span的区别); 反过来设置==*/
.div_span_1_cls,.div_span_2_cls,.div_span_3_cls{
background: green;
display: inline;
}
span{
background-color: red;
display: block;
width: 200px;
}
<div class="div_span_1_cls">Samy张</div>
<div class="div_span_2_cls">Samy张</div>
<div class="div_span_3_cls">Samy张</div>
<span class="span_div_3_cls">Samy张S</span>
<span class="span_div_3_cls">Samy张S</span>
<span class="span_div_3_cls">Samy张S</span>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# position 定位方式
设置:
static
默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right z-index 声明)。relative
生成相对定位的元素,相对于其正常位置进行定位。absolute
生成绝对定位的元素,相对于值不为 static的第一个父元素进行定位。 fixed也可以;fixed
生成绝对定位的元素,相对于浏览器窗口进行定位 ;悬浮设置后,宽高会自适应,记得设置width: 100%
,及定位设置;一个固定定位元素不会保留它原本在页面应有的空隙。(老IE不支持)inherit
继承; 规定从父元素继承 position 属性的值。
定位: left(左),right(右),top(上),bottom(下)离页面顶点的距离
绝对定位和fixed定位的比较
共同点:改变行内元素的呈现方式,都脱离了文档流;
不同点:absolute的**”根元素“是可以设置的,fixed的“根元素”固定为浏览器窗口**
position: absolute;
- 相对于 非static的先辈元素定位;(正常情况); 相对于最近的已定位的祖先元素, 有已定位(指position不是static的元素)祖先元素, 以最近的祖先元素为参考标准。如果无已定位祖先元素, 以body元素为偏移参照基准, 完全脱离了标准文档流。
- 如果先辈元素全是
static
,那么相对于视口定位;(特殊情况)
position:fixed
- 相对于视口定位;(正常情况)
- 如果先辈元素有
非none
的transform
属性,那么相对于该先辈元素定位(不注意容易产生BUG)
失效的解决办法是:对父级元素设置transform: none; 或者display:inline
# position:fixed;在android下无效怎么处理?
手机上兼容设置:所以说并不是iOS不支持fixed,只是fixed的元素不是相对手机屏幕固定的。
通过以下设置处理:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
# float 浮动属性
left
左浮动
right
右浮动
clear
清除浮动; clear:both
注:设置 Flex 布局后,子元素的 Float 布局将失效
# overflow 溢出处理
hidden
隐藏超出层大小的内容
scroll
无论内容是否超出层大小都添加滚动条
auto
超出时自动添加滚动条
# margin 属性
margin
属性为给定元素设置所有四个(上左下右)方向的外边距属性。普通元素的 百分比margin 都是相对于容器的
宽度
计算的绝对定位元素的 百分比margin 相对于其定位祖先元素的宽度计算的
上下margin会重叠:只会发生在
block
元素上,(取最大值)解决重叠方法:
- 父元素设置
BFC
(如overflow:hidden;如position:absolute等) - 父元素设置
border
/padding
- 父元素设置
当 margin 的值为
auto
时。浏览器会自动选择一个合适的margin来应用(自动分配剩余空间)- 需要元素是 块状元素
- 需要元素 设置宽度
margin 可以为 负值
# z-index网页的层叠等级
z-index 层覆盖先后顺序(优先级); 大于0的数字;数字大的最上面
其实一个网页是分为好多层的,具体层次和层叠等级如下图:
z-index为正值 》 z-index: 0/auto 》 行内元素 》 浮动元素 》 块级元素 》z-index为负数 》 background/border
# 设置DOM元素不显示在浏览器可视范围内
# visibility:hidden/visible、display:none、z-index=-1、opacity:0 及比较;【OVDZ】
- opacity:0,该元素隐藏起来了,但不会改变页面布局,并且,如果该元素已经绑定了一些事件,如click事件也能触发
- visibility:hidden,该元素隐藏起来了,但不会改变页面布局,但是不会触发该元素已经绑定的事件; (重绘)
- display:none, 把元素隐藏起来,并且会改变页面布局,可以理解成在页面中把该元素删掉; (回流+重绘)
- z-index=-1置于其他元素下面; 注意:z-index的数值不跟单位。z-index的数字越高越靠前,并且值必须为整数和正数(正数的整数)。
总括:
最基本的:设置visibility属性为hidden,或者设置display属性为none
技巧性:设置透明度为0,设置z-index位置在-1000, 设置宽高为0
1. display:none;
- DOM结构:浏览器不会渲染display属性为none的元素,不占据空间,意思就是页面上没有它的一席之地,你在开发者模式中选不中那个元素。
- 事件监听:无法进行DOM事件监听。
- 性能:动态改变此属性时会引起重排,性能较差。
- 继承:不会被子元素继承,因为子元素也不被渲染。
- transtion过渡不支持display。
2. visibility:hidden;
- DOM结构:元素被隐藏了,浏览器会渲染visibility属性为hidden的元素,占据空间,意思就是页面上有它的空间,在开发者模式中能选中那个元素。
- 事件监听:无法进行DOM事件监听。
- 性能:动态改变此属性时会引起重绘,性能较高。
- 继承:会被子元素继承,子元素通过设置visibility:visible;来显示自身,使子元素取消自身隐藏。
- transtion:visibility会立即显示,隐藏时会延时。
3. opacity:0;
- DOM结构:opacity属性值为0时透明度为100%,元素隐藏,占据空间,opacity值为0到1,为1时显示元素。
- 事件监听:可以进行DOM事件监听。
- 性能:提升为合成层,不会引发重绘,性能较高。
- 继承:会被子元素继承,子元素不能通过设置opacity:1;来取消隐藏。。
- transtion:opacity可以延时显示与隐藏。
# 行内(inline)/块级(block)/空(void)元素
首先:CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,
如span默认display属性值为“inline”,是“行内”元素; div的display默认值为“block”,则为“块级”元素;
行内(inline)元素:宽度和高度由内容决定
,与其他元素共占一行的元素; 内边距的top/bottom(padding-top/padding-bottom)和外边距的top/bottom(margin-top/margin-bottom)都不可改变(也就是padding和margin的left和right是可以设置的),就是里面文字或图片的大小。
如:i a b span select strong
块级(block)元素:默认宽度由父容器决定,默认高度由内容决定
,独占一行并且可以设置宽高的元素;
如:div ul ol li dl dt dd h1 h2 h3 h4…p
浏览器还有默认的天生inline-block【空】元素(拥有内在尺寸,可设置高宽,但不会自动换行)
如:<input> 、<img> 、<button> 、<texterea> 、<label>
在日常开发中,经常使用 CSS 的 display
属性来打破两者的壁垒:display: inline-block
,使它们拥有更多的状态。常见的空元素: 不同浏览器(版本)、HTML4(5)、CSS2等实际略有差异;
<br> <hr> <img> <input> <link> <meta>
//鲜为人知的是:
<area> <base> <col> <command> <embed> <keygen> <param> <source> <track> <wbr>
2
3
说明:
- 块级标签可以设置width和height
- 行内标签不可以设置width和height(它的width由内容决定,height由font-size决定)
- block水平的元素inline-block化后,IE6/7没有换行符间隙问题,其他浏览器均有;
{ display: inline-block; *display: inline; *zoom: 1; }
inline水平的元素inline-block后,所有主流浏览器都有换行符/空格间隙问题;
# Flex 布局
Flex 是 Flexible Box 的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。
行内元素也可以使用 Flex 布局。display: inline-flex;
Webkit 内核的浏览器,必须加上-webkit
前缀。display: -webkit-flex; /* Safari */
注意,设为 Flex 布局以后,子元素的float、clear和vertical-align属性将失效
。
# 父元素属性(6个)
属性名 | 属性值 | 备注 |
---|---|---|
display | flex | 定义了一个flex容器,它的直接子元素会接受这个flex环境 |
flex-direction | row,row-reverse,column,column-reverse | 决定主轴的方向 |
flex-wrap | nowrap,wrap,wrap-reverse | 如果一条轴线排不下,如何换行 |
flex-flow | [flex-direction] , [flex-wrap] | 是flex-direction 属性和flex-wrap 属性的简写形式,默认值为row nowrap |
justify-content | flex-start,flex-end,center,space-between,space-around | 设置或检索弹性盒子元素在主轴(横轴)方向上的对齐方式 |
align-items | flex-start,flex-end,center,baseline,stretch | 设置或检索弹性盒子元素在侧轴(纵轴)方向上的对齐方式 |
# 子元素属性(6个)
属性名 | 属性值 | 备注 |
---|---|---|
order | [int] | 默认情况下flex order会按照书写顺训呈现,可以通过order属性改变,数值小的在前面,还可以是负数。 |
flex-grow | [number] | 设置或检索弹性盒的扩展比率,根据弹性盒子元素所设置的扩展因子作为比率来分配剩余空间 |
flex-shrink | [number] | 设置或检索弹性盒的收缩比率,根据弹性盒子元素所设置的收缩因子作为比率来收缩空间 |
flex-basis | [length], auto | 设置或检索弹性盒伸缩基准值 |
align-self | auto,flex-start,flex-end,center,baseline,stretch | 设置或检索弹性盒子元素在侧轴(纵轴)方向上的对齐方式,可以覆盖父容器align-items的设置 |
flex | [number] | 占比 |
# ES基础
# 基本类型及判断方式
# 【SSBNNU】 S
# 基本数据类型
Symbol(ES6)、String、Boolean、Number、Null、Undefined; 简写:SSBNNU 栈(stack)
# 内置对象
Object 是 JavaScript 中所有对象的父对象
数据封装类对象:Object、Array、Boolean、Number 和 String
其他对象:Function、Arguments、Math、Date、RegExp、Error
# 判断方式对比
===能用于判断null和undefined,因为这两种类型的值都是唯一的
undefined === null; // false,类型不相同 undefined !== null; // true, 类型不相同
1
2typeof返回一个表示数据类型的字符串,返回结果包括:number、boolean、string、symbol、object、undefined、function等7种数据类型,*但不能判断null、array、object等,*但是
typeof null === 'object'
;instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。但它不能检测null 和 undefined; 基础类型没有
__proto__
**constructor作用和instanceof非常相似。**但constructor检测 Object与instanceof不一样,还可以处理基本数据类型的检测。但它不能检测null 和 undefined
const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
Object.prototype.toString.call() 最准确最常用的方式;
toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。
对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。
及ES6新加入的方法:Array.isArray():检测某个值是否为数组(ES6)
# instanceOf原理
# 对象的深拷贝操作比较
//定义检测数据类型的功能函数
function checkedType(target) {
return Object.prototype.toString.call(target).slice(8, -1) //获取从第九个到倒数第二个字符
}//targetType ==='Object'; 比如[object String]获取 String
function simpleClone(obj) {//浅拷贝
let newObj = {};
for (let i in obj) {
newObj[i] = obj[i];
}
return newObj;
}
//方式一:直接用instancof/typeof判断;【推荐】简洁;
function deepClone(obj){
var newObj= obj instanceof Array?[]:{};
for(var i in obj){
newObj[i]=typeof obj[i]=='object'? deepClone(obj[i]):obj[i];
}
return newObj;
}
function deepClone(obj) {//第二种方式;跟方式一类似;
let result;
if (typeof obj == 'object') {
result = isArray(obj) ? [] : {}
for (let i in obj) {
result[i] = isObject(obj[i])||isArray(obj[i])?deepClone(obj[i]):obj[i]
}
} else {
result = obj
}
return result
}
function isObject(obj) {
return Object.prototype.toString.call(obj) == "[object Object]"
}
function isArray(obj) {
return Object.prototype.toString.call(obj) == "[object Array]"
}
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
29
30
31
32
33
34
35
36
37
38
# 隐藏转换
所有对象都有valueOf方法,valueOf方法对于:如果存在任意原始值,它就默认将对象转换为表示它的原始值。
类型先通过
valueOf
再toString
进行隐式转换;
let a = {
value: 0,
valueOf: function() {
this.value++;
return this.value;
}
};
console.log(a == 1 && a == 2);
2
3
4
5
6
7
8
# 数组
# for循环
- 简单for:
- 循环for-in(最慢):**循环遍历的是对象的属性,而不是数组的索引。**因此, for-in 遍历的对象便不局限于数组,还可以遍历对象。
- forEach(最快):没有返回值;
a.forEach(function(item, idx, arr){})
- map:有返回值
- for-of(ES6+):
# 方法及比较
forEach/map 不能 break 和 return;
for-in 缺点更加明显,它不仅遍历数组中的元素,还会遍历自定义的属性,甚至原型链上的属性都被访问到。而且,遍历数组元素的顺序可能是随机的。 for in更适合遍历对象;
for-of优点:推荐
- 跟 forEach 相比,可以正确响应 break, continue, return。
- for-of 循环不仅支持数组,还支持大多数类数组对象,例如 DOM nodelist 对象。
- 其不仅可以遍历数组,还可以遍历类数组对象和其他可迭代对象。
- for-of 循环也支持字符串遍历,它将字符串视为一系列 Unicode 字符来进行遍历。
- for-of 也支持 Map 和 Set (两者均为 ES6 中新增的类型)对象遍历。
# forEach 、for in、 for of各自的特点是什么?
forEach
只能遍历数组,且不能中断(break等无效); 可查看后面forEach内部源码的实现;for in
遍历的是对象的可枚举属性;结合hasOwnPropery方法可以判断某属性是否是该对象的实例属性;for of
遍历的是对象的迭代器属性;
记住,for in遍历的是数组的索引(即键名),而for of遍历的是数组元素值。
for of遍历的只是数组内的元素,而不包括数组的原型属性method和索引name
# 常用方法
栈方法 push
() 可以接收任意数量的参数,把他们逐个添加到数组的末尾,返回修改后数组的长度
pop
() 从数组末尾移除最后一项,返回移除的项
队列方法 unshift
() 向数组前端添加任意个项并返回新数组的长度
shift
() 移除数组的第一项并返回该项
排序 sort
(compare): compare函数接收两个参数,如果返回负数,则第一个参数位于第二个参数前面;如果返回零,则两个参数相等;如果返回正数,第一个参数位于第二个参数后面; (a,b) => (b-a) // 降序,升序相反
Array.sort();如果不带参数调用sort,数组以字母顺序进行排序升序; 如果数组中包含undefined元素,它们会被排到数组的尾部
操作方法 concat
(数组 | 一个或多个元素) ;合并数组,返回新数组
slice
(起始位置 ,[结束位置]);切分数组,返回新数组,新数组不包含结束位置的项
splice
(起始位置,删除的个数,[插入的元素]) // 删除|插入|替换数组,返回删除的元素组成的数组,会修改原数组
reverse()
: 反转数组元素的顺序
Array.join()
是Array.split()方法的逆向操作;以指定分隔符连接,如果不指定,默认以,连接;
Array.toString()
: 返回一个字符串,表示指定的数组及其元素。跟join类似;
# 其他遍历相关方法
some()、every()、filter()、map()、forEach()都是对数组的每一项调用函数进行处理。
– some()、every()的返回值 :true / false
– filter()、map()的返回值 :一个新数组
– forEach()无返回值。当然forEach也可以改变原数组:return
使用some()、every()、filter()、map()、forEach()都不改变原数组。
find返回通过指定条件(函数内判断)的数组的第一个元素的值; 不创建新数组
arr.filter()、includes()、find()、findIndex(); indexOf(), lastIndexOf()//方法对大小写敏感
# 归并方法: reduce/reduceRight
对数组中的元素依次处理,将上次结果作为下次处理的输入,最后得到最终结果。接收一个函数作为累加器;
数组只有一项或是个空数组不做遍历操作; 如果归并的数组为空,则会报错;
# 遍历方法类似原理
# foreach的类似实现原理
// if (!Array.prototype.forEach) {
Array.prototype.forEach = function(fn) {
for (var i = 0; i < this.length; i++) {
fn(this[i], i, this);
}
};
// }
["a", "b", "c"].forEach(function(value, index, array) {
console.log((value, "Is in position " + index + " out of " + (array.length - 1)));
});
2
3
4
5
6
7
8
9
10
# 常用算法
# 合并
1.终极篇
[1,2,3,4].concat([5,6]) //[1,2,3,4,5,6]
[...[1,2,3,4],...[4,5]] //[1,2,3,4,5,6]
let arrA = [1, 2], arrB = [3, 4]
Array.prototype.push.apply(arrA, arrB))//arrA值为[1,2,3,4]
2
3
4
2.开始篇
let arr=[1,2,3,4];
[5,6].map(item=>{
arr.push(item)
})
//arr值为[1,2,3,4,5,6],注意不能直接return出来,return后只会返回[5,6]
2
3
4
5
# 判断是否包含值
1.终极篇
[1,2,3].includes(4) //false
[1,2,3].indexOf(4) //-1 如果存在换回索引
[1, 2, 3].find((item)=>item===3)) //3 如果数组中无值返回undefined
[1, 2, 3].findIndex((item)=>item===3)) //2 如果数组中无值返回-1
2
3
4
includes(),find(),findIndex()是 ES6的api
2.开始篇
[1,2,3].some(item=>{
return item===3
}) //true 如果不包含返回false
2
3
# 最大值
var arr = [1, 2, 3, 4];
console.log(Math.max(...arr)); //4
console.log(Math.max.call(this, 1, 2, 3, 4))
console.log(Math.max.call(this, ...arr)); //4
console.log(Math.max.apply(this, arr)); //4
console.log(
arr.reduce((prev, cur, curIndex, arr) => {
return Math.max(prev, cur);
}, 0)
); //4
//两个功能是一样的;比如:func是Math.max的话;
//return func(..._args);
//return func.apply(null, _args);
2
3
4
5
6
7
8
9
10
11
12
13
14
Math.max()是Math对象内置的方法,参数是字符串;
# 求两数组中不同元素
const arr1 = [1,2,3,4,5]
const arr2 = [2,3,1,0,5]
const ans = arr1.filter(v => arr2.indexOf(v) == -1 )//[4]
const a = new Set(arr1) const b = new Set(arr2)
new Set([...a, ...b])//并集
new Set([...a].filter(v => b.has(v)))//交集
new Set([...a].filter(v => !b.has(v)))//差集
2
3
4
5
6
7
8
# 原型链
# 类/TS
# 异步
# VUE
# 生命周期
# 各个生命周期及描述 (8+2)
生命周期 | 描述 |
---|---|
beforeCreate | 组件实例被创建之初,组件的属性生效之前;vue实例的挂载元素$el和数据对象 data都是undefined, 还未初始化 |
created | 组件实例已经完全创建,属性也绑定,完成了 data数据初始化;但真实 dom 还没有生成,$el 还不可用 |
beforeMount | 在挂载开始之前被调用:相关的 render 函数首次被调用;vue实例的$el和data都初始化了 |
mounted | el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子;在 mounted 被调用前,Vue 已经将编译好的模板挂载到页面上,所以在 mounted 中可以访问操作 DOM。 |
beforeUpdate | 组件数据更新之前调用,发生在虚拟 DOM 打补丁之前 |
update | 组件数据更新之后 |
activited | keep-alive 专属,组件被激活时调用 |
deactivated | keep-alive 专属,组件被销毁时调用 |
beforeDestory | 组件销毁前调用 |
destoryed | 组件销毁后调用 |
# 生命周期总括【要点】
8 个生命周期,创建前/创建后、挂载前/挂载后、更新前/更新后、销毁前/销毁后。Vue 生命周期的作用
是方便我们通过它的生命周期,在业务代码中更好地操作数据,实现相关功能。这些函数称为生命周期 hook
8个生命周期过程:Vue 实例(组件)从其初始化到销毁和删除都经历生命周期;
- 创建前/后:
- 在 beforeCreated 阶段,Vue 实例的挂载元素
$el
和数据对象 data 以及事件还未初始化。 - 在 created 阶段,Vue 实例的数据对象 data 以及方法的运算有了,
$el
还没有。
- 在 beforeCreated 阶段,Vue 实例的挂载元素
- 载入前/后:
- 在 beforeMount 阶段,
render
函数首次被调用,Vue 实例的 $el 和 data 都初始化了,但还是挂载在虚拟的 DOM 节点上。 - 在 mounted 阶段,Vue 实例挂载到实际的 DOM 操作完成,一般在该过程进行 Ajax 交互。
- 在 beforeMount 阶段,
- 更新前/后:
- 在数据更新之前调用,即发生在虚拟 DOM 重新渲染和打补丁之前,调用 beforeUpdate。
- 在虚拟 DOM 重新渲染和打补丁之后,会触发 updated 方法。
- 销毁前/后:
- 在执行实例销毁之前调用 beforeDestory,此时实例仍然可以调用。
- 在执行 destroy 方法后,对 data 的改变不会再触发周期函数,说明此时 Vue 实例已经解除了事件监听以及和 DOM 的绑定,但是 DOM 结构依然存在
# watch、computed与methods的联系和区别【要点】
watch 就是监听的意思,其专门用来观察和响应Vue实例上的数据的变动。
能使用watch
属性的场景基本上都可以使用computed
属性,而且computed
属性开销小,性能高,因此能使用computed
就尽量使用computed
属性
想要执行异步或昂贵的操作以响应不断变化的数据时,这时watch
就派上了大用场。
其应用场景一般都是搜索框之类的,需要不断的响应数据的变化;如果要在数据变化的同时进行异步操作或者是比较大的开销,那么watch为最佳选择。
computed 就是计算属性,其可以当成一个data数据来使用。直接使用,不用像方法那样调用();
# v-if
和v-show
指令
v-if
指令是直接销毁和重建DOM达到让元素显示和隐藏的效果; 每次显示状态更改时,代价通常会更大。v-show
指令是通过修改元素的display
CSS属性(display:none
)让其显示或者隐藏; 但是display:none
, 把元素隐藏起来,并且会改变页面布局一般来说,
v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。因此,- 如果需要非常频繁地切换,则使用
v-show
较好; - 如果在运行时条件很少改变,则使用
v-if
较好。
总括:
另一方面,v-show 成本较低,因为它仅切换元素的CSS显示属性。所以如果必须经常切换元素,则 v-show 会提供比 v-if 更好,更优化的结果。
就加载元素的初始渲染成本而言,v-if 不会渲染最初隐藏的元素的节点,而 v-show 会渲染其 CSS
display
属性被设置为none
的元素。- 如果需要非常频繁地切换,则使用
# v-if
和 v-for
指令
不推荐同时使用 v-if
和 v-for
; 当 v-if
与 v-for
一起使用时,v-for
具有比 v-if
更高的优先级。这意味着 v-if
将分别重复运行于每个 v-for
循环中。
v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,必要情况下应该替换成 computed 属性。
# vue中常用的命令
- v-if/v-show区别 判断是否隐藏
- v-for 数据循环出来
- v-model 实现双向绑定
- v-bind v-bind:class:绑定一个属性;
- v-on
# 更新检测
# 数组更新检测 vm.$set
由于 JavaScript 的限制,Vue 不能检测以下数组的变动:
- 当你利用索引直接设置一个数组项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
解决办法:
解决上面1问题: Vue 提供了以下操作方法:
Vue.set(vm.items, indexOfItem, newValue)// Vue.set
vm.$set(vm.items, indexOfItem, newValue)// vm.$set,Vue.set的一个别名
vm.items.splice(indexOfItem, 1, newValue)// Array.prototype.splice; 底层实现方式;
2
3
解决上面2问题:Vue 提供了以下操作方法:
vm.items.splice(newLength)// Array.prototype.splice
示例:通过socket监听设备在线状态
sockets: {
sDevices: function (value) {
const index = this.data.findIndex(item => value.id === item.id)
if (index >= 0) {
this.data.splice(index, 1, value)
}
}
},
2
3
4
5
6
7
8
# 对象更新检测
还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:
对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以使用Vue.set (object, propertyName, value) / vm.$set (object, propertyName, value)
来实现为对象添加响应式属性
# Vue 组件间通信几种方式【要点】
Vue 组件间通信只要指以下 3 类通信:父子组件通信、隔代组件通信、兄弟组件通信
总括:常用的三种: props / $emit
, EventBus ($emit / $on)
, Vuex ;
# 监听子组件事件
# $emit
【父集监听:v-on:xx="postFontSize += 0.1"
; 子集发送:v-on:click="$emit('xx')"
】
v-on:input="$emit('input', $event.target.value)"
详细可见自定义事件;
# Vuex/Router
# Vuex几个核心模块【要点】
vuex主要由五部分组成:state、 getters、mutations、actions、module组成。
主要包括以下几个模块:(sgmam) + mapG amsg m
- State:定义了应用状态的数据结构,可以在这里设置默认的初始状态。
- Getter:允许组件从 Store 中获取数据,
mapGetters 辅助函数
仅仅是将 store 中的 getter 映射到局部计算属性
。 - Mutation:是唯一更改 store 中状态的方法,且必须是同步函数。
- Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。
- Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。
使用流程是: 组件中可以直接调用上面五个部分除了module; Vuex 适用于 父子、隔代、兄弟组件通信
组件不允许直接修改属于 store 实例的 state,而应执行 action 来分发 (dispatch) 事件通知 store 去改变,我们最终达成了 Flux (opens new window) 架构。这样约定的好处是,我们能够记录所有 store 中发生的 state 改变,同时实现能做到记录变更 (mutation)、保存状态快照、历史回滚/时光旅行的先进的调试工具。
应用级的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事务; 异步逻辑应该封装在action中。
# HTML5 History 模式
vue-router
默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。
如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面
。
const router = new VueRouter({
mode: 'history',
routes: [...]
})
2
3
4
当你使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id
,也好看!
不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id
就会返回 404,这就不好看了。
# 后端配置
nginx 常用; try_files $uri $uri/ /index.html;
你也许注意到 router.push
、 router.replace
和 router.go
跟 window.history.pushState
、 window.history.replaceState
和 window.history.go
类似;
# hash 模式和 history 模式的区别【要点】
- url 展示上,hash 模式有“#”,history 模式没有
- 刷新页面时,hash 模式可以正常加载到 hash 值对应的页面,而 history 没有处理的话,会返回 404,一般需要后端将所有页面都配置重定向到首页路由。
try_files $uri $uri/ /index.html;
- 兼容性。hash 可以支持低版本浏览器和 IE。
# React
# 生命周期
# 图示
React 16.3 版本之前 生命周期
React 新版 生命周期
# Webpack
# 其他
Nginx
node 工具脚手架