秋招前端面经

秋招前端面经

面了挺多公司,可是没几个大厂,不敢投,下面按照本身的经历分为国企和非国企和共性问题的面经javascript


非国企

譬如招银网络、顺丰科技、4399等中小厂css

JS\HTML\CSS

cookie、session、localStorage、sessionStorage区别

具体答案自行查找,我感受每次回答都答不到面试官想要我答的点html

回流(重排)与重绘

回流: 当渲染的一部分元素更改本身的宽高等,致使从新构建布局,就产生了回流。
重绘: 当一个元素自身的高度没改变,只改变了背景颜色的,发生重绘。
回流一定重绘,当重绘不必定回流。前端

避免回流和重绘方法

  1. 避免操做DOM
  2. 避免设置多层内联样式,由于每个都会形成回流,样式合并在一个外部类,这样当该元素的class属性被操做时,只会产生一个reflow。
  3. 将须要屡次回流的元素position属性设为absolute或fixed,这样该元素就会脱离文档流,它的变化不会影响其余元素变化。
  4. 避免使用table布局,
  5. 避免使用css的JavaScript表达式

闭包

概念:vue

红宝书:有权访问另外一个函数做用域中的变量的函数html5

优势:java

  1. 防止函数执行完后,变量被销毁,使其保存在内存中。
  2. 经过闭包和当即执行函数来封装函数, 全局变量可能会形成命名冲突,使用闭包不用担忧这个问题,由于它是私有化,增强了封装性,这样保护变量的安全。

缺点:因为它是驻留在内存中,会增大内存使用量,使用不当很容易形成内存泄露。node

Web前端性能优化

其实你能够从用户输入url经历的过程进行分析。mysql

浏览器缓存:
首先会检查浏览器缓存,那就可使用它。添加http缓存头Expires,使组件被缓存,下次访问的时候,就能够减小没必要要的HTPP请求,从而提升加载速度。es6

DNS解析:
DNS解析,能够设置meta标签的http-equiv要求DNS预解析,好比遇到超连接就提早解析。

HTTP链接上:
常见的减小http请求如静态资源合并,js和css合并,雪碧图就不讲了。
服务器在完成 HTTP 请求以后不断开 TCP 链接而是挂起,后续有 HTTP 请求能够直接在这个 TCP 链接上发送;缺点是保持长链接会消耗服务端的资源。
HTTP/2 多路复用的特性容许多个 HTTP 请求在同一个 TCP 链接上发送,能够节省屡次创建 TCP 链接的时间。

http1.0 和 1.1的区别(本身从简)

  1. 缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来作为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
  2. 带宽优化及网络链接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是须要某个对象的一部分,而服务器却将整个对象送过来了,而且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它容许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和链接。
  3. 错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
  4. Host头处理,在HTTP1.0中认为每台服务器都绑定一个惟一的IP地址,所以,请求消息中的URL并无传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上能够存在多个虚拟主机(Multi-homed Web Servers),而且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中若是没有Host头域会报告一个错误(400 Bad Request)。
  5. 长链接,HTTP 1.1支持长链接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP链接上能够传送多个HTTP请求和响应,减小了创建和关闭链接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,必定程度上弥补了HTTP1.0每次请求都要建立链接的缺点。

http1.x 和 2.0 的区别(本身从简)

  1. 二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在自然缺陷,文本的表现形式有多样性,要作到健壮性考虑的场景必然不少,二进制则不一样,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
  2. 多路复用(MultiPlexing),即链接共享,即每个request都是是用做链接共享机制的。一个request对应一个id,这样一个链接上能够有多个request,每一个链接的request能够随机的混杂在一块儿,接收方能够根据request的 id将request再归属到各自不一样的服务端请求里面。
  3. header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,并且每次都要重复发送,HTTP2.0使用encoder来减小须要传输的header大小,通信双方各自cache一份header fields表,既避免了重复header的传输,又减少了须要传输的大小。
  4. 服务端推送(server push),同SPDY同样,HTTP2.0也具备server push功能。

https的原理

  1. 客户端发送请求到服务端
  2. 服务端返回公钥和证书
  3. 客户端验证证书合法性,客户端生成一个随机数密钥,经过证书中的公钥加密并发送给服务端。
  4. 服务端使用私钥解密,获取随机数密钥后,而后把内容经过该密钥进行对称加密。发送给客户端。
  5. 由于客户端也知道这个密钥,因此客户端能够还原信息。

可能会给中间人攻击,解决方法能够用第三方安全证书来认证。

判断对象的属性是原型的仍是本身的

  1. hasOwnProperty()函数用于指示一个对象自身(不包括原型链)是否具备指定名称的属性。若是有,返回true,不然返回false。

  2. (属性名称 in 对象) 无论属性是原型的仍是实例的,只要存在就返回ture不然返回false

那么咱们能够利用这两个方法作一个对比,若是实例中没有且存在了这个属性,那么就是原型的

原型链

详细能够看https://juejin.im/post/58f94c9bb123db411953691b

下面简略说明:
当访问一个对象的某个属性时,会先在这个对象自己属性上查找,若是没有找到,则会去它的__proto__隐式原型上查找,若是尚未找到就会再的__proto__中查找,这样一层一层向上查找最后到object就会造成一个链式结构,咱们称为原型链。

  1. 每个构造函数都有一个prototype指针,他指向它的原型对象。
  2. 每个原型对象都有一个constructor指针,它指向它的构造函数。
  3. 每个对象都有一个__proto__指针,它指向它的原型对象。
  4. 对象的原型对象也有__proto__指针指向上一个原型对象,最终__proto__指针通常指向object,由于它是基础object的。

这样链式的链接集合就构成了原型链。

继承(通常问优缺点)

原型继承(原型式继承)

在object()函数内部, 先建立一个临时性的构造函数, 而后将传入的对象做为这个构造函数的原型,最后返回了这个临时类型的一个新实例.

function object(o){
	function F(){}
	F.prototype = o;
	return new F();
}
复制代码

缺点:不是类式继承,而是原型式基础,缺乏了类的概念

原型链继承

将父类实例做为子类的原型对象

function Parent () {
  this.names = ['kevin', 'daisy'];
}
function Child () {
 
}
Child.prototype = new Parent();
 
var child1 = new Child();
child1.names.push('yayu');
console.log(child1.names); // ["kevin", "daisy", "yayu"]
var child2 = new Child();
console.log(child2.names); // ["kevin", "daisy", "yayu"]
复制代码

缺点:全部子类的实例的原型都共享同一个父类实例的属性和方法。

构造函数继承

在函数中运行父级构造函数

// 子类
function Sub(){
  Super.call(this)
  this.property = 'Sub Property'
}
复制代码

缺点:
父类函数没有共享,浪费内存。
没法继承原型链上的属性和方法。

组合继承

原型继承和构造函数继承的组合

// 子类
function Sub(){
  Super.call(this)
  this.property = 'Sub Property'
}
Sub.prototype = new Super()
// 注意这里new Super()生成的超类对象并无constructor属性,故需添加上
Sub.prototype.constructor = Sub
复制代码

缺点:父级构造函数被调用两次,子类实例也有两份,浪费内存。
实际上子类上会拥有超类的两份属性,只是子类的属性覆盖了原型对象上的属性。

寄生式继承(和原型式继承差很少)

原型式继承套个壳子,增长你要传入的参数。

function objectCreate(obj){
  function F(){}
  F.prototype = obj
  return new F()
}
function createSubObj(superInstance){
  var clone = objectCreate(superInstance)
  clone.property = 'Sub Property'
  return clone
}
复制代码

缺点:依旧没有类的概念

寄生组合式继承

在子构造函数中执行父级函数,并建立Object.create(父级的原型对象)复值给obj,再修改obj的constructor的指针指向子构造函数,最后obj做为子构造函数的原型对象。

function Sub(){
    Super.call(this);
}
var proto = Object.create(Super.prototype);
proto.constructor = Sub;
Sub.prototype = proto ;
复制代码

跨域,基本都考(通常会往深了问,具体过程自行查找)

同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。

  1. jsonp:动态建立script标签,利用script标签不受同源政策约束来跨域获取数据(只能用get请求);
  2. cors跨域:前端正常请求附带Origin字段附带网址,服务端接收到后,更据本身的跨域规则,若是容许访问,响应头设置Access-Control-Allow-Origin字段。
  3. html5的postMessage方法跨域:不能和服务端交换数据,只能在两个窗口(iframe)之间交换数据。A页面有B页面的引用。A用postMessage方法发送消息,B页面经过message事件监听并接受消息:

状态码

1xx:指示信息–表示请求已接收.
2xx:成功-请求已接受并返回响应头
200:请求已成功,返回响应头。
3xx:重定向–要完成请求必须进行更进一步的操做。
301:请求的资源已被永久移到新位置。
302:临时重定向
304:缓存的内容并未改变。
4xx:客户端错误–请求有语法错误或请求没法实现。
400:请求无效,前端提交数据的字段名称或者是字段类型和后台的实体类不一致。
401:请求要身份验证。
403:资源不可用。
404:找不到页面。
5xx:服务器端错误–服务器未能实现合法的请求。
500:服务器遇到未知情况,没法处理。
503:服务器过载或维护。

post和get请求区别

  1. get在浏览器回退时是无害的,而post会再次请求
  2. get请求会被浏览器主动缓存,而post不会,除非手动设置
  3. get请求参数会被完整保留在浏览历史记录里,而post中的参数不会被保留
  4. get 请求在url中传送的参数有长度限制,而post没有
  5. get参数经过url传递,poet放在request body中

盒子模型

元素的内容(content),元素的内边距(padding),元素的边框(border),元素的外边距(margin)四个部分

BFC

块格式化上下文(block formatting context) 是Web页面的可视化CSS渲染出的一部分。

BFC是页面CSS 视觉渲染的一部分,用于决定块盒子的布局及浮动相互影响范围的一个区域。
BFC的一个最重要的效果是,让处于BFC内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。
利用BFC能够闭合浮动,防止与浮动元素重叠。

BFC的建立方法
  1. 根元素或其它包含它的元素
  2. 浮动 (元素的float不为none)
  3. 绝对定位或固定定位元素 (元素的position为absolute或fixed)
  4. 行内块inline-blocks(元素的 display: inline-block)
  5. overflow的值不为visible的元素
边距重叠

若是子div中有margin-top会外层div塌陷。 解决设置:父设置,overflow:hidden便可。

深拷贝的方法,(说了JSON.stringfiy+JSON.parse)

1:
var copy = JSON.parse(JSON.stringify(person))
复制代码

缺点:1.没法拷贝对象中的function、undefined、null、RegExp属性

2:
function deepCopy(obj) {
  var result = Array.isArray(obj) ? [] : {};
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      if (typeof obj[key] === 'object' && obj[key]!==null) {
        result[key] = deepCopy(obj[key]);   //递归复制
      } else {
        result[key] = obj[key];
      }
    }
  }
  return result;
}
复制代码

缺点就是复杂点

访问url

  1. 输入url,常见的http协议的端口号是80,https是443
  2. 查看浏览器是否有缓存,其中分为强制缓存和相对缓存
  3. dns查询,用迭代查询和递归查询结合的方式查询
  4. TCP三次握手创建链接(可能会问三次握手的过程和目的)
  5. 浏览器向服务器发送HTTP请求
  6. 浏览器接收响应 服务器在收到浏览器发送的HTTP请求以后,处理完的结果以HTTP的Response对象返回,主要包括状态码,响应头,响应报文三个部分。
  7. 页面渲染,涉及浏览器的渲染过程和回流,重绘。

*柯里化

柯里化是把一个多参数函数转换为一个嵌套的一元函数的过程

const addCurried = function(x){
    return function(y){
        return x + y; 
    }
}

// 使用方法
addCurried(4)(4)
// 8
复制代码

可以进行延迟计算,就像add(1)(2)同样,1比2先传入,2就会被延迟计算,在特定的场景里,有必定的应用意义。

节流防抖

函数节流

用在连续点击div时,
是为了限制函数一段时间内只能执行一次,在延时的时间内,方法若被触发,则直接退出方法。

let throttle = (func, wait) => {
  let timer;
  return function() {
    if(timer) {
      return ;
    }
    var self = this;
    var args = arguments;
    timer = setTimeout(function() {
      func.apply(self, args);
      timer = null;
    }, wait)
  } 
}
复制代码
函数防抖

用在搜索输入时,
函数防抖在执行目标方法时,会等待一段时间。当又执行相同方法时,若前一个定时任务未执行完,则 clear 掉定时任务,从新定时。

let debounce = function(func,wait) {
  let timer;
  return function(){
    let args = arguments;
    var self = this;
    clearTimeout(timer);
    timer = setTimeout(function(){
      func.apply(self,args);
    }, wait);
  }
}
复制代码

浏览器缓存(http缓存)

考察控制字段,这个不熟,每次答感受都答不到面试官的点上,自行查找合适的解释。

*域名收敛域名发散

DNS解析过程

  1. 浏览器根据地址去自己缓存中查找dns解析记录,若是有,则直接返回IP地址,不然浏览器会查找操做系统中(hosts文件)是否有该域名的dns解析记录,若是有则返回。
  2. 若是浏览器缓存和操做系统hosts中均无该域名的dns解析记录,或者已通过期,此时就会向域名服务器发起请求来解析这个域名。
  3. 请求会先到LDNS(本地域名服务器),让它来尝试解析这个域名,若是LDNS也解析不了,则直接到根域名解析器请求解析。
  4. 根域名解析器经过迭代查询和递归查询结合的方式来查找解析,最后返回相应的IP地址。

做用域链

做用域链就是一个有序的栈,保证对执行环境有权访问的全部变量和函数的有序访问。

其余具体自行查找,我也不能说具体。

执行上下文

不一样于做用域链。

其余具体自行查找,我也不能说具体。

JS事件模型

DOM2事件模型

  1. 事件捕获阶段
  2. 事件处理阶段
  3. 事件冒泡阶段

dom.addEventListener(‘click’,function(){},true) 第一个参数侦听的事件,第二个参数为触发事件执行的方法,第三个true捕获阶段执行,false冒泡阶段执行

IE事件流:叫作事件冒泡。从点击的元素向上传播。用ele.attachEvent(‘onclick’, function(){ }); 只支持冒泡阶段

new()操做到底作了什么

  1. 建立一个新的空对象
  2. 将构造函数的做用域赋给新对象(所以 this 就指向了这个新对象)
  3. 执行构造函数中的代码(为这个新对象添加属性)
  4. 返回新对象
var obj = new Base();
// 等价于
var obj  = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
//随后经过Base.prototype.xxx = () => {}为Base添加方法时,obj也同时拥有此方法
复制代码

let const var区别

let:

  1. 不能重复声明一个变量
  2. 了他拥有块级做用域
  3. let声明不提早
  4. 总之,在代码块内,使用let命令声明变量以前,该变量都是不可用的。这在语法上,称为“暂时性死区”

const:

  1. 不能重复声明,要初始化
  2. 假如声明的是对象则容许修改对象的值

promise(!important)

原理
优缺点
适用场景
本身代码实现
了解async和await

不写了,太多

本身对请求作多一层处理,针对不一样状态码响应

css画一个三角形

.triangle_border_up{
  width:0;
  height:0;
  border-width: 30px; /*上右下左 上为0为上三角形*/
  border-style:solid;
  border-color:transparent transparent transparent #333;/*透明 透明 透明 灰*/
}
复制代码

三栏布局,两边定宽中间自适应(圣杯布局、双飞翼布局)

实现三栏水平布局,其中left、right分别位于左右两侧,left宽度为200px,right宽度为300px,main处在中间,宽度自适应。

圣杯布局
  1. 圣杯布局是一种相对布局
  2. 将主体部分的三个子元素都设置左浮动
  3. 设置main宽度为width:100%,让其单独占满一行
  4. 设置left和right 负的外边距。负的margin-left会让元素沿文档流向左移动,若是负的数值比较大就会一直移动到上一行。
  5. 接下来只要把left和right分别移动到这两个留白就能够了。可使用相对定位移动 left和right部分。
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>实现三栏水平布局之圣杯布局</title>
  <style type="text/css"> .container { padding: 0 300px 0 200px; } .left, .main, .right { position: relative; min-height: 130px; float: left; } .left { left: -200px; margin-left: -100%; background: green; width: 200px; } .right { right: -300px; margin-left: -300px; background-color: red; width: 300px; } .main { background-color: blue; width: 100%; } </style>
</head>
<body>
<div class="container"> 
&emsp;&emsp;<div class="main">main</div> 
&emsp;&emsp;<div class="left">left</div> 
&emsp;&emsp;<div class="right">right</div> 
</div>
</body>
</html>
复制代码
双飞翼布局

圣杯布局和双飞翼布局解决问题的方案在前一半是相同的,也就是三栏所有float浮动,但左右两栏加上负margin让其跟中间栏div并排,以造成三栏布局。
双飞翼布局比圣杯布局多使用了1个div,少用大体4个css属性(圣杯布局container的 padding-left和padding-right这2个属性,加上左右两个div用相对布局position: relative及对应的right和left共4个属性,;而双飞翼布局子div里用margin-left和margin-right共2个属性,比圣杯布局思路更直接和简洁一点。简单提及来就是:双飞翼布局比圣杯布局多建立了一个div,但不用相对布局了。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>实现三栏水平布局之双飞翼布局</title>
  <style type="text/css"> .left, .main, .right { float: left; min-height: 130px; text-align: center; } .left { margin-left: -100%; background: green; width: 200px; } .right { margin-left: -300px; background-color: red; width: 300px; } .main { background-color: blue; width: 100%; } .content{ margin: 0 300px 0 200px; } </style>
</head>
<body>
<div class="container"> 
&emsp;&emsp;<div class="main">
    &emsp;&emsp;<div class="content">main</div> 
    </div>
&emsp;&emsp;<div class="left">left</div> 
&emsp;&emsp;<div class="right">right</div> 
</div>
</body>
</html>
复制代码
flex布局
  1. 项目根据内容进行弹性布局
  2. 经过order属性设置排列顺序
  3. 经过项目属性flex-grow设置main的放大比例,将空余的空间用main来填充,使三个项目不满一整行;默认为0,也就是对剩余空间不作处理。
  4. 经过项目属性flex-basis 设置left和right的固定宽度
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>实现三栏水平布局之Flex布局</title>
  <style type="text/css"> .container{ display: flex; min-height: 130px; } .main{ flex-grow: 1; background-color: blue; } .left{ order: -1; flex-basis: 200px; background-color: green; } .right{ flex-basis: 300px; background-color: red; } </style>
</head>
<body>
<div class="container"> 
&emsp;&emsp;<div class="main">main</div> 
&emsp;&emsp;<div class="left">left</div> 
&emsp;&emsp;<div class="right">right</div> 
</div>
</body>
</html>
复制代码
绝对定位布局

绝对定位使元素的位置与文档流无关,所以不占据空间。这一点与相对定位不一样,相对定位实际上被看做普通流定位模型的一部分,由于元素的位置相对于它在普通流中的位置。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>实现三栏水平布局之绝对定位布局</title>
  <style type="text/css"> .container{ position: relative; } .main,.right,.left{ top: 0; height: 130px; } .main{ margin: 0 300px 0 200px; background-color: blue; } .right{ position: absolute; width: 300px; right: 0; background-color: red; } .left{ position: absolute; width: 200px; background-color: green; left: 0; } </style>
</head>
<body>
<div class="container"> 
&emsp;&emsp;<div class="main">main</div> 
&emsp;&emsp;<div class="left">left</div> 
&emsp;&emsp;<div class="right">right</div> 
</div>
</body>
</html>
复制代码

CSS水平垂直居中

水平居中:

  1. 行内元素:
text-align: center;
复制代码
  1. 有宽度的块元素:
margin: 0 auto;
复制代码

垂直居中:

  1. 单行内容垂直居中:
line-height: height; //height父级高度
复制代码
  1. 绝对定位:
position: absolute;
top: 50%;
transform: translate(0, -50%);
复制代码
  1. flex布局:
display: flex;
flex-direction: column;
justify-content: center;
复制代码

方法不少:绝对定位、margin: auto、弹性布局、相对定位、table布局。
具体自行查找

CSS选择器优先级

  1. 在属性后面加!important会覆盖任何样式
  2. 做为style属性写在元素内的样式
  3. id选择器
  4. 类选择器
  5. 标签选择器
  6. 通配选择器

雪碧图(精灵图)

雪碧图又叫精灵图原理就是将一些小图标合并到一张图上,用css的背景定位来设置要显示的部分。

VUE

建议先阅读网上的源码解析

vue生命周期

  1. beforeCreate(建立前) 在数据观测和初始化事件还未开始
  2. created(建立后) 完成数据观测,属性和方法的运算,初始化事件,$el属性尚未显示出来
  3. beforeMount(载入前) 在挂载开始以前被调用,相关的render函数首次被调用。实例已完成如下的配置:编译模板,把data里面的数据和模板生成html。注意此时尚未挂载html到页面上。
  4. mounted(载入后) 在el 被新建立的 vm.$el 替换,并挂载到实例上去以后调用。实例已完成如下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程当中进行ajax交互。
  5. beforeUpdate(更新前) 在数据更新以前调用,发生在虚拟DOM从新渲染和打补丁以前。能够在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
  6. updated(更新后) 在因为数据更改致使的虚拟DOM从新渲染和打补丁以后调用。调用时,组件DOM已经更新,因此能够执行依赖于DOM的操做。然而在大多数状况下,应该避免在此期间更改状态,由于这可能会致使更新无限循环。该钩子在服务器端渲染期间不被调用。
  7. beforeDestroy(销毁前) 在实例销毁以前调用。实例仍然彻底可用。
  8. destroyed(销毁后) 在实例销毁以后调用。调用后,全部的事件监听器会被移除,全部的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
  9. activated:keep-alive组件被激活
  10. deactivited: keep-alive组件被移除

简述每一个周期具体适合哪些场景?

  1. beforeCreate:能够在这加loading事件,在加载实例时触发。
  2. created:初始化完成时的事件写在这里,如在这里结束loading,异步请求也适合在这里调用。
  3. mounted:挂载元素,获取到dom节点。
  4. updated:若是对数据统一处理,在这里写上相应的函数。
  5. beforeDestroy:能够作一个肯定中止事件的确认框。

聊聊你对Vue.js的template编译的理解?

先转化成AST树,再获得的render函数返回VNode(Vue的虚拟DOM节点)

  1. 经过compile编译器把template编译成AST语法树(abstract syntax tree 抽象语法树 即 源代码的抽象语法结构的树状表现形式),compile是createCompiler的返回值,createCompiler是用以建立编译器的。另外compile还负责合并option。
  2. AST会通过generate(将AST语法树转化成render funtion字符串的过程)获得render函数,render的返回值是VNode,VNode是Vue的虚拟DOM节点,里面有(标签名、子节点、文本等等)

vue数据双向绑定

采用数据劫持结合发布者-订阅者模式的方式,经过Object.defineProperty()来劫持各个属性的setter,getter,在数据变更时发布消息给订阅者,触发相应的监听回调。

vue实现数据双向绑定主要步骤:

  1. 须要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter。 这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化。
  2. compile解析模板指令,将模板中的变量替换成数据,而后初始化渲染页面视图,并将每一个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变更,收到通知,更新视图。
  3. Watcher订阅者是Observer和Compile之间通讯的桥梁,主要作的事情是:
    ①在自身实例化时往属性订阅器(dep)里面添加本身
    ②自身必须有一个update()方法
    ③待属性变更dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
  4. MVVM做为数据绑定的入口,整合Observer、Compile和Watcher三者,经过Observer来监听本身的model数据变化,经过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通讯桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变动的双向绑定效果。

*更加详细请看源码和解析

vue组件间的数据通讯

  1. 父组件与子组件传值 父组件传给子组件:子组件经过props方法接受数据;
    子组件传给父组件:$emit 方法传递参数
  2. 非父子组件间的数据传递,兄弟组件传值eventBus,就是建立一个事件中心,至关于中转站,能够用它来传递事件和接收事件。
    emit 传值,on() 接收值。项目比较小时,用这个比较合适。
  3. 整个状态存储:vuex

vue路由

Vue的路由实现:hash模式 和 history模式

  1. hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
    特色:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动做,对服务端安全无害,hash不会从新加载页面。 hash 模式下,仅 hash 符号以前的内容会被包含在请求中,如 www.xxx.com,所以对于后端来讲,即便没有作到对路由的全覆盖,也不会返回 404 错误。
  2. history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()能够对浏览器历史记录栈进行修改,以及popState事件的监听到状态变动。
    history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 www.xxx.com/items/id。后端… /items/id 的路由处理,将返回 404 错误。

*详细自行查找

vue-router导航钩子

  1. 全局导航钩子:
    (1)前置守卫:跳转前进行拦截。
    router.beforeEach(to, from, next)
    (2)后置钩子
    router.afterEach((to, from) => {})
  2. 组件内的钩子 beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
  3. 单独路由独享组件。 beforeEnter: (to, from ,next)

vuex中mutation 和action的区别

改变状态的方式,同步逻辑封装在mutation中,异步逻辑封装在action中。 详细自行查找

vue中引入组件的步骤

  1. components目录建立组件文件,如indexPage.vue。 注意:script必定要export default{}
  2. 在须要的页面(组件)引入组件(2种方式): (1)es6的import..from...
    import indexPage from '@/components/indexPage.vue'
    (2)CommonJS的require()
  3. 组件注册:注入到vue子组件的components属性上面,components{indexPage}
  4. 在template视图view中使用。

注意:命名时若是是indexPage,使用的时候用index-page

vue实现流程

看源码解析

一、第一步:解析模板成render函数
template 二、第二步:响应式开始监听
object.defineProperty
data属性代理到vm上
三、第三步:首次渲染,显示页面,且绑定依赖
(1)为什么要监听get,直接监听set不行吗?
①data中有不少属性,有些被用到,有些可能不被用到(data中没有人访问,就不会用get,如没有{{aaa}}指的就是aaa没有被访问)
②被用到的会走到get,不被用到的不会走到get
③未走到get中的属性,set的时候也无需关心
④避免没必要要的重复渲染
四、第四步:data属性变化,触发rerender defineProperty, get, set
(1)修改属性,被响应式的set监听到
(2)set中执行updateComponent
(3)updateComponent从新执行vm._render()
(4)生成的vnode和prevVnode,经过Patch进行对比
渲染到html

国企

通常问项目还有计算机基础 具体看共性问题

都会问的问题

数据结构

排序、树、图……

数据库

mysql、mongodb、存储过程……

计算机网络

……
这些建议查找网上面经,会比个人要详细不少,要是打算进国企,则必定要有好聊的实习和项目,还有必定的基础,基本上剩下的就看学历了。

先写到这,有缘往后再补充。