面试完50我的后我写下这篇总结

  2019年的春节来的彷佛格外的早,过完年相信不少童鞋都开始蠢蠢欲动了;笔者总结了多篇教程,结合平时本身的面试经历,整理了这份文档,但愿帮助你们来突击一下前端知识的盲区。文章很长很长很长。。。。(建议先收藏,技术大佬请Ctrl+F4,面向基础css

整理不易,但愿你们关注公众号【前端壹读】,更多前端原创好文等着你。html

1、CSS

盒模型

  CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距margin,边框border,填充padding,和实际内容content。盒模型容许咱们在其它元素和周围元素边框之间的空间放置元素。前端

Box-Model.jpg

box-sizing: content-box(W3C盒模型,又名标准盒模型):元素的宽高大小表现为内容的大小。 box-sizing: border-box(IE盒模型,又名怪异盒模型):元素的宽高表现为内容 + 内边距 + 边框的大小。背景会延伸到边框的外沿。vue

CSS3的新特性

  • word-wrap 文字换行
  • text-overflow 超过指定容器的边界时如何显示
  • text-decoration 文字渲染
  • text-shadow文字阴影
  • gradient渐变效果
  • transition过渡效果 transition-duration:过渡的持续时间
  • transform拉伸,压缩,旋转,偏移等变换
  • animation动画

transition和animation的区别:node

  Animation和transition大部分属性是相同的,他们都是随时间改变元素的属性值,他们的主要区别是transition须要触发一个事件才能改变属性,而animation不须要触发任何事件的状况下才会随时间改变属性值,而且transition为2帧,从from .... to,而animation能够一帧一帧的。react

CSS选择器及其优先级

  • !important
  • 内联样式style=""
  • ID选择器#id
  • 类选择器/属性选择器/伪类选择器.class.active[href=""]
  • 元素选择器/关系选择器/伪元素选择器html+div>span::after
  • 通配符选择器*

BFC

BFC(Block Formatting Context)格式化上下文,是Web页面中盒模型布局的CSS渲染模式,指一个独立的渲染区域或者说是一个隔离的独立容器。 webpack

BFC应用

  • 防止margin重叠
  • 清除内部浮动
  • 自适应两(多)栏布局
  • 防止字体环绕

触发BFC条件

  • 根元素
  • float的值不为none
  • overflow的值不为visible
  • display的值为inline-block、table-cell、table-caption
  • position的值为absolute、fixed

BFC的特性

  • 内部的Box会在垂直方向上一个接一个的放置。
  • 垂直方向上的距离由margin决定
  • bfc的区域不会与float的元素区域重叠。
  • 计算bfc的高度时,浮动元素也参与计算
  • bfc就是页面上的一个独立容器,容器里面的子元素不会影响外面元素。

div水平居中

  1. 行内元素
.parent {
    text-align: center;
}
复制代码
  1. 块级元素
.son {
    margin: 0 auto;
}
复制代码
  1. flex布局
.parent {
    display: flex;
    justify-content: center;
}
复制代码
  1. 绝对定位定宽
.son {
    position: absolute;
    width: 宽度;
    left: 50%;
    margin-left: -0.5*宽度
}
复制代码
  1. 绝对定位不定宽
.son {
    position: absolute;
    left: 50%;
    transform: translate(-50%, 0);
}
复制代码
  1. left/right: 0
.son {
    position: absolute;
    width: 宽度;
    left: 0;
    right: 0;
    margin: 0 auto;
}
复制代码

div垂直居中

  1. 行内元素
.parent {
    height: 高度;
}
.son {
    line-height: 高度;
}
复制代码
  1. table
.parent {
  display: table;
}
.son {
  display: table-cell;
  vertical-align: middle;
}
复制代码
  1. flex
.parent {
    display: flex;
    align-items: center;
}
复制代码
  1. 绝对定位定高
.son {
    position: absolute;
    top: 50%;
    height: 高度;
    margin-top: -0.5高度;
}
复制代码
  1. 绝对定位不定高
.son {
    position: absolute;
    top: 50%;
    transform: translate( 0, -50%);
}
复制代码
  1. top/bottom: 0;
.son {
    position: absolute;
    height: 高度;
    top: 0;
    bottom: 0;
    margin: auto 0;
}
复制代码

绝对定位和相对定位

  • absolute 绝对定位 相对于最近的已定位的祖先元素, 有已定位(指position不是static的元素)祖先元素, 以最近的祖先元素为参考标准。若是无已定位祖先元素, 以body元素为偏移参照基准, 彻底脱离了标准文档流。ios

  • fixed 固定定位的元素会相对于视窗来定位,这意味着即使页面滚动,它仍是会停留在相同的位置。一个固定定位元素不会保留它本来在页面应有的空隙。css3

共同点:改变行内元素的呈现方式,都脱离了文档流;不一样点:absolute的”根元素“是能够设置的,fixed的“根元素”固定为浏览器窗口web

flex布局

采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的全部子元素自动成为容器成员,称为 Flex 项目(flex item),简称“项目”。

flex.jpeg

  1. 父元素属性
属性名 属性值 备注
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 设置或检索弹性盒子元素在侧轴(纵轴)方向上的对齐方式
  1. 子元素属性
属性名 属性值 备注
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的设置

让元素消失

visibility:hidden、display:none、z-index=-一、opacity:0

  1. opacity:0,该元素隐藏起来了,但不会改变页面布局,而且,若是该元素已经绑定了一些事件,如click事件也能触发
  2. visibility:hidden,该元素隐藏起来了,但不会改变页面布局,可是不会触发该元素已经绑定的事件
  3. display:none, 把元素隐藏起来,而且会改变页面布局,能够理解成在页面中把该元素删掉
  4. z-index=-1置于其余元素下面

清除浮动

  1. 在浮动元素后面添加 clear:both 的空 div 元素,
<div class="container">
    <div class="left"></div>
    <div class="right"></div>
    <div style="clear:both"></div>
</div>
复制代码
  1. 给父元素添加 overflow:hidden 或者 auto 样式,触发BFC。
<div class="container">
    <div class="left"></div>
    <div class="right"></div>
</div>
复制代码
.container{
    width: 300px;
    background-color: #aaa;
    overflow:hidden;
    zoom:1;   /*IE6*/
}
复制代码
  1. 使用伪元素,也是在元素末尾添加一个点并带有 clear: both 属性的元素实现的。
<div class="container clearfix">
    <div class="left"></div>
    <div class="right"></div>
</div>
复制代码
.clearfix{
    zoom: 1; /*IE6*/
}
.clearfix:after{
    content: ".";
    height: 0;
    clear: both;
    display: block;
    visibility: hidden;
}
复制代码

推荐使用第三种方法,不会在页面新增div,文档结构更加清晰。

calc函数

calc函数是css3新增的功能,可使用calc()计算border、margin、pading、font-size和width等属性设置动态值。

#div1 {
    position: absolute;
    left: 50px;
    width: calc( 100% / (100px * 2) );
    //兼容写法
    width: -moz-calc( 100% / (100px * 2) );
    width: -webkit-calc( 100% / (100px * 2) );
    border: 1px solid black;
}
复制代码

注意点:

  • 须要注意的是,运算符先后都须要保留一个空格,例如:width: calc(100% - 10px);
  • calc()函数支持 "+", "-", "*", "/" 运算;
  • 对于不支持 calc() 的浏览器,整个属性值表达式将被忽略。不过咱们能够对那些不支持 calc()的浏览器,使用一个固定值做为回退。

移动端rem

rem官方定义『The font size of the root element』,即根元素的字体大小。rem是一个相对的CSS单位,1rem等于html元素上font-size的大小。因此,咱们只要设置html上font-size的大小,就能够改变1rem所表明的大小。

(function () {
    var html = document.documentElement;
    function onWindowResize() {
        html.style.fontSize = html.getBoundingClientRect().width / 20 + 'px';
    }
    window.addEventListener('resize', onWindowResize);
    onWindowResize();
})();
复制代码

移动端1px

通常来讲,在PC端浏览器中,设备像素比(dpr)等于1,1个css像素就表明1个物理像素;可是在retina屏幕中,dpr广泛是2或3,1个css像素再也不等于1个物理像素,所以比实际设计稿看起来粗很多。

  1. 伪元素+scale
<style> .box{ width: 100%; height: 1px; margin: 20px 0; position: relative; } .box::after{ content: ''; position: absolute; bottom: 0; width: 100%; height: 1px; transform: scaleY(0.5); transform-origin: 0 0; background: red; } </style>

<div class="box"></div>

复制代码
  1. border-image
div{
    border-width: 1px 0px;
    -webkit-border-image: url(border.png) 2 0 stretch;
    border-image: url(border.png) 2 0 stretch;
}
复制代码

两边宽度固定中间自适应的三栏布局

圣杯布局和双飞翼布局是前端工程师须要平常掌握的重要布局方式。二者的功能相同,都是为了实现一个两侧宽度固定,中间宽度自适应的三栏布局。

圣杯布局

<style> body{ min-width: 550px; } #container{ padding-left: 200px; padding-right: 150px; } #container .column{ float: left; } #center{ width: 100%; } #left{ width: 200px; margin-left: -100%; position: relative; right: 200px; } #right{ width: 150px; margin-right: -150px; } </style>
<div id="container">
    <div id="center" class="column">center</div>
    <div id="left" class="column">left</div>
    <div id="right" class="column">right</div>
</div>
复制代码

Layout.gif

双飞翼布局

<style> body { min-width: 500px; } #container { width: 100%; } .column { float: left; } #center { margin-left: 200px; margin-right: 150px; } #left { width: 200px; margin-left: -100%; } #right { width: 150px; margin-left: -150px; } </style>
<div id="container" class="column">
    <div id="center">center</div>
</div>
<div id="left" class="column">left</div>
<div id="right" class="column">right</div>

复制代码

伪类和伪元素

css引入伪类和伪元素概念是为了格式化文档树之外的信息。也就是说,伪类和伪元素都是用来修饰不在文档树中的部分。

before-after.jpg

伪类

伪类存在的意义是为了经过选择器找到那些不存在DOM树中的信息以及不能被常规CSS选择器获取到的信息。

  1. 获取不存在与DOM树中的信息。好比标签的:link、visited等,这些信息不存在与DOM树结构中,只能经过CSS选择器来获取;
  2. 获取不能被常规CSS选择器获取的信息。好比:要获取第一个子元素,咱们没法用常规的CSS选择器获取,但能够经过 :first-child 来获取到。

weilei.png

伪元素

伪元素用于建立一些不在文档树中的元素,并为其添加样式。好比说,咱们能够经过:before来在一个元素前增长一些文本,并为这些文本添加样式。虽然用户能够看到这些文本,可是这些文本实际上不在文档树中。常见的伪元素有:::before::after::first-line::first-letter::selection::placeholder

所以,伪类与伪元素的区别在于:有没有建立一个文档树以外的元素。

::after和:after的区别

在实际的开发工做中,咱们会看到有人把伪元素写成:after,这实际是 CSS2 与 CSS3新旧标准的规定不一样而致使的。

CSS2 中的伪元素使用1个冒号,在 CSS3 中,为了区分伪类和伪元素,规定伪元素使用2个冒号。因此,对于 CSS2 标准的老伪元素,好比:first-line:first-letter:before:after,写一个冒号浏览器也能识别,但对于 CSS3 标准的新伪元素,好比::selection,就必须写2个冒号了。

CSS画圆半圆扇形三角梯形

/* 半圆 */
.half-circle{
    height: 50px;
    border-radius: 50px 50px 0 0;
}
/* 扇形 */
.sector{
    border-radius: 100px 0 0;
}
/* 三角 */
.triangle{
    width: 0px;
    height: 0px;
    background: none;
    border: 50px solid red;
    border-color: red transparent transparent transparent;
}
/* 梯形 */
.ladder{
    width: 50px;
    height: 0px;
    background: none;
    border: 50px solid red;
    border-color: red transparent transparent transparent;
}
复制代码

2、JS

JS数据类型

JS基本有5种简单数据类型:String,Number,Boolean,Null,Undefined。引用数据类型:Object,Array,Function。

判断数据类型的方法

在写业务逻辑的时候,常常要用到JS数据类型的判断,面试常见的案例深浅拷贝也要用到数据类型的判断。

typeof

console.log(typeof 2);               // number
console.log(typeof true);            // boolean
console.log(typeof 'str');           // string
console.log(typeof undefined);       // undefined
console.log(typeof []);              // object 
console.log(typeof {});              // object
console.log(typeof function(){});    // function
console.log(typeof null);            // object
复制代码

优势:可以快速区分基本数据类型 缺点:不能将Object、Array和Null区分,都返回object

instanceof

console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false 
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true
复制代码

优势:可以区分Array、Object和Function,适合用于判断自定义的类实例对象 缺点:Number,Boolean,String基本数据类型不能判断

Object.prototype.toString.call()

var toString = Object.prototype.toString;
 
console.log(toString.call(2));                      //[object Number]
console.log(toString.call(true));                   //[object Boolean]
console.log(toString.call('str'));                  //[object String]
console.log(toString.call([]));                     //[object Array]
console.log(toString.call(function(){}));           //[object Function]
console.log(toString.call({}));                     //[object Object]
console.log(toString.call(undefined));              //[object Undefined]
console.log(toString.call(null));                   //[object Null]
复制代码

优势:精准判断数据类型 缺点:写法繁琐不容易记,推荐进行封装后使用

var,let,const的区别

letES6 新添加申明变量的命令,它相似于 var,可是有如下不一样:

  • var 声明的变量,其做用域为该语句所在的函数内,且存在变量提高现象
  • let 声明的变量,其做用域为该语句所在的代码块内,不存在变量提高
  • const声明的变量不容许修改

null和undefined区别

Undefined类型只有一个值,即undefined。当声明的变量还未被初始化时,变量的默认值为undefined。用法:

  • 变量被声明了,但没有赋值时,就等于undefined。
  • 调用函数时,应该提供的参数没有提供,该参数等于undefined。
  • 对象没有赋值的属性,该属性的值为undefined。
  • 函数没有返回值时,默认返回undefined。

Null类型也只有一个值,即null。null用来表示还没有存在的对象,经常使用来表示函数企图返回一个不存在的对象。用法

  • 做为函数的参数,表示该函数的参数不是对象。
  • 做为对象原型链的终点。

定义函数的方法

  1. 函数声明
//ES5
function getSum(){}
function (){}//匿名函数
//ES6
()=>{}
复制代码
  1. 函数表达式
//ES5
var getSum=function(){}
//ES6
let getSum=()=>{}
复制代码
  1. 构造函数
const getSum = new Function('a', 'b' , 'return a + b')
复制代码

JS做用域的理解

JS中的做用域分为两种:全局做用域和函数做用域。函数做用域中定义的变量,只能在函数中调用,外界没法访问。没有块级做用域致使了if或for这样的逻辑语句中定义的变量能够被外界访问,所以ES6中新增了let和const命令来进行块级做用域的声明。

更多做用域的了解能够看JS做用域

闭包的理解

简单来讲闭包就是在函数里面声明函数,本质上说就是在函数内部和函数外部搭建起一座桥梁,使得子函数能够访问父函数中全部的局部变量,可是反之不能够,这只是闭包的做用之一,另外一个做用,则是保护变量不受外界污染,使其一直存在内存中,在工做中咱们仍是少使用闭包的好,由于闭包太消耗内存,不到万不得已的时候尽可能不使用。

更多闭包的内容能够看JS闭包

数组去重

let arr = [1,'1',2,'2',1,2,'x','y','f','x','y','f'];
function unique1(arr){
	let result = [arr[0]];
	for (let i = 1; i < arr.length; i++) {
		let item = arr[i];
		if(result.indexOf(item) == -1){
			result.push(item);
		}
	}
	return result;
}
console.log(unique1(arr));
复制代码

更多JS去重的方法JS数组去重

call,apply和bind区别

三个函数的做用都是将函数绑定到上下文中,用来改变函数中this的指向;三者的不一样点在于语法的不一样。

fun.call(thisArg[, arg1[, arg2[, ...]]])
fun.apply(thisArg, [argsArray])
复制代码

因此applycall的区别是call方法接受的是若干个参数列表,而apply接收的是一个包含多个参数的数组。

而bind()方法建立一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供以前提供一个给定的参数序列。

var bindFn = fun.bind(thisArg[, arg1[, arg2[, ...]]])
bindFn()
复制代码

Demos:

var name = 'window';
var sayName = function (param) {
    console.log('my name is:' + this.name + ',my param is ' + param)
};
//my name is:window,my param is window param
sayName('window param')

var callObj = {
    name: 'call'
};
//my name is:call,my param is call param
sayName.call(callObj, 'call param');


var applyObj = {
    name: 'apply'
};
//my name is:apply,my param is apply param
sayName.apply(applyObj, ['apply param']);

var bindObj = {
    name: 'bind'
}
var bindFn = sayName.bind(bindObj, 'bind param')
//my name is:bind,my param is bind param
bindFn();
复制代码

==和===区别

  • ==, 两边值类型不一样的时候,要先进行类型转换,再比较
  • ===,不作类型转换,类型不一样的必定不等。

==类型转换过程:

  1. 若是类型不一样,进行类型转换
  2. 判断比较的是不是 null 或者是 undefined, 若是是, 返回 true .
  3. 判断二者类型是否为 string 和 number, 若是是, 将字符串转换成 number
  4. 判断其中一方是否为 boolean, 若是是, 将 boolean 转为 number 再进行判断
  5. 判断其中一方是否为 object 且另外一方为 string、number 或者 symbol , 若是是, 将 object 转为原始类型再进行判断

深拷贝和浅拷贝

浅拷贝

function simpleClone(obj) {
    var result = {};
    for (var i in obj) {
        result[i] = obj[i];
    }
    return result;
}
复制代码

深拷贝,遍历对象中的每个属性

function deepClone(obj) {
    let result;
    if (typeof obj == 'object') {
        result = isArray(obj) ? [] : {}
        for (let i in obj) {
            //isObject(obj[i]) ? deepClone(obj[i]) : obj[i]
            //多谢"朝歌在掘金"指出,多维数组会有问题
            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]"
}
复制代码

防抖和节流

debounce_throttle.png

防抖

function debounce(fn, delay) {
  let timer = null;
  return function () {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, arguments);
    }, delay);
  }
}
复制代码

节流

function throttle(fn, cycle) {
  let start = Date.now();
  let now;
  let timer;
  return function () {
    now = Date.now();
    clearTimeout(timer);
    if (now - start >= cycle) {
      fn.apply(this, arguments);
      start = now;
    } else {
      timer = setTimeout(() => {
        fn.apply(this, arguments);
      }, cycle);
    }
  }
}

复制代码

cookie,sessionStorage和localStorage

  • cookie用来保存登陆信息,大小限制为4KB左右
  • localStorage是Html5新增的,用于本地数据存储,保存的数据没有过时时间,通常浏览器大小限制在5MB
  • sessionStorage接口方法和localStorage相似,但保存的数据的只会在当前会话中保存下来,页面关闭后会被清空。
名称 生命期 大小限制 与服务器通讯
cookie 通常由服务器生成,可设置失效时间。若是在浏览器端生成Cookie,默认是关闭浏览器后失效 4KB 每次都会携带在HTTP头中,若是使用cookie保存过多数据会带来性能问题
localStorage 除非被清除,不然永久保存 5MB 仅在浏览器中保存,不与服务器通讯
sessionStorage 仅在当前会话下有效,关闭页面或浏览器后被清除 5MB 仅在浏览器中保存,不与服务器通讯

0.1+0.2!=0.3怎么处理

把须要计算的数字升级(乘以10的n次幂)成计算机可以精确识别的整数,等计算完成后再进行降级(除以10的n次幂),即:

(0.1*10 + 0.2*10)/10 == 0.3 //true
复制代码

更多关于浮点数精度处理请看JS中浮点数精度问题

JS实现继承

首先建立一个父类

// 定义一个动物类
function Animal(name, color) {
    // 属性
    this.name = name || 'Animal';
    this.color = color || ['black'];
    // 实例方法
    this.sleep = function () {
        console.log(this.name + '正在睡觉!');
    }
}
// 原型方法
Animal.prototype.eat = function (food) {
    console.log(this.name + '正在吃:' + food);
};
复制代码

原型链继承

new了一个空对象,这个空对象指向Animal而且Cat.prototype指向了这个空对象,这种就是基于原型链的继承。

function Cat(name) {
    this.name = name || 'tom'
}
Cat.prototype = new Animal()

var cat = new Cat()
cat.color.push('red')
cat.sleep() //tom正在睡觉!
cat.eat('fish') //tom正在吃:fish
console.log(cat.color) //["black", "red"]
console.log(cat instanceof Animal) //true
console.log(cat instanceof Cat) //true
var new_cat = new Cat()
console.log(new_cat.color) //["black", "red"]
复制代码
  • 特色:基于原型链,既是父类的实例,也是子类的实例。
  • 缺点:1.没法实现多继承;2.全部新实例都会共享父类实例的属性。

构造继承

function Dog(name) {
    Animal.call(this)
    this.name = name || 'mica'
}
var dog = new Dog()
dog.color.push('blue')
dog.sleep() // mica正在睡觉!
dog.eat('bone') //Uncaught TypeError: dog.eat is not a function
console.log(dog.color) //["black", "blue"]
console.log(dog instanceof Animal) //false
console.log(dog instanceof Dog) //true
var new_dog = new Dog()
console.log(new_dog.color) //["black"]
复制代码
  • 特色:能够实现多继承(call多个),解决了全部实例共享父类实例属性的问题。
  • 缺点:1.只能继承父类实例的属性和方法;2.不能继承原型上的属性和方法。

组合继承

function Mouse(name){
    Animal.call(this)
    this.name = name || 'jerry'
}
Mouse.prototype = new Animal()
Mouse.prototype.constructor = Mouse

var mouse = new Mouse()
mouse.color.push('yellow)
mouse.sleep() //jerry正在睡觉!
mouse.eat('carrot') //jerry正在吃:carrot
console.log(mouse instanceof Animal)//true
console.log(mouse instanceof Mouse)//true
var new_mouse = new Mouse()
console.log(new_mouse.color) //["black"]
复制代码
  • 特色:能够继承实例属性/方法,也能够继承原型属性/方法
  • 缺点:调用了两次父类构造函数,生成了两份实例

3、vue

mvc和mvvm理解

MVC

MVC即Model View Controller,简单来讲就是经过controller的控制去操做model层的数据,而且返回给view层展现。

mvc.png

  • View 接受用户交互请求
  • View 将请求转交给Controller处理
  • Controller 操做Model进行数据更新保存
  • 数据更新保存以后,Model会通知View更新
  • View 更新变化数据使用户获得反馈

MVVM

MVVM即Model-View-ViewModel,将其中的 View 的状态和行为抽象化,让咱们能够将UI和业务逻辑分开。MVVM的优势是低耦合、可重用性、独立开发。

mvvm.jpg

  • View 接收用户交互请求
  • View 将请求转交给ViewModel
  • ViewModel 操做Model数据更新
  • Model 更新完数据,通知ViewModel数据发生变化
  • ViewModel 更新View数据

MVVM模式和MVC有些相似,但有如下不一样

  • ViewModel 替换了 Controller,在UI层之下
  • ViewModel 向 View 暴露它所须要的数据和指令对象
  • ViewModel 接收来自 Model 的数据

归纳起来,MVVM是由MVC发展而来,经过在Model之上而在View之下增长一个非视觉的组件未来自Model的数据映射到View中。

响应原理

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

生命周期函数

  • beforeCreate(建立前) vue实例的挂载元素$el和数据对象 data都是undefined, 还未初始化
  • created(建立后) 完成了 data数据初始化, el还未初始化
  • beforeMount(载入前) vue实例的$el和data都初始化了, 相关的render函数首次被调用
  • mounted(载入后) 此过程当中进行ajax交互
  • beforeUpdate(更新前)
  • updated(更新后)
  • beforeDestroy(销毁前)
  • destroyed(销毁后)

组件data为何返回函数

组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data。若是单纯的写成对象形式,就使得全部组件实例共用了一份data,形成了数据污染。

vue给对象新增属性页面没有响应

因为Vue会在初始化实例时对属性执行getter/setter转化,因此属性必须在data对象上存在才能让Vue将它转换为响应式的。Vue提供了$set方法用来触发视图更新。

export default {
    data(){
        return {
            obj: {
                name: 'fei'
            }
        }
    },
    mounted(){
        this.$set(this.obj, 'sex', 'man')
    }

}
复制代码

v-if和v-show区别

v-if 是真正的条件渲染,由于它会确保在切换过程当中条件块内的事件监听器和子组件适当地被销毁和重建;也是惰性的:若是在初始渲染时条件为假,则什么也不作——直到条件第一次变为真时,才会开始渲染条件块。

v-show 就简单得多——无论初始条件是什么,元素老是会被渲染,而且只是简单地基于 CSS 的 “display” 属性进行切换。

因此,v-if 适用于在运行时不多改变条件,不须要频繁切换条件的场景;v-show 则适用于须要很是频繁切换条件的场景。

v-model双向绑定原理

v-model本质上是语法糖,v-model 在内部为不一样的输入元素使用不一样的属性并抛出不一样的事件。

  • text 和 textarea 元素使用 value 属性和 input 事件
  • checkbox 和 radio 使用 checked 属性和 change 事件
  • select 字段将 value 做为 prop 并将 change 做为事件

因此咱们能够v-model进行以下改写:

<input v-model="sth" />
// 等同于
<input :value="sth" @input="sth = $event.target.value" />
复制代码

这个语法糖必须是固定的,也就是说属性必须为value,方法名必须为:input。

知道了v-model的原理,咱们能够在自定义组件上实现v-model。

//Parent
<template>
    {{num}}
    <Child v-model="num">
</template>
export default {
    data(){
        return {
            num: 0
        }
    }
}

//Child
<template>
    <div @click="add">Add</div>
</template>
export default {
    props: ['value'],
    methods:{
        add(){
            this.$emit('input', this.value + 1)
        }
    }
}
复制代码

key的做用

  1. 让vue精准的追踪到每个元素,高效的更新虚拟DOM
  2. 触发过渡
<transition>
  <span :key="text">{{ text }}</span>
</transition>
复制代码

当text改变时,这个元素的key属性就发生了改变,在渲染更新时,Vue会认为这里新产生了一个元素,而老的元素因为key不存在了,因此会被删除,从而触发了过渡。

scoped属性做用

在Vue文件中的style标签上有一个特殊的属性,scoped。当一个style标签拥有scoped属性时候,它的css样式只能用于当前的Vue组件,可使组件的样式不相互污染。若是一个项目的全部style标签都加上了scoped属性,至关于实现了样式的模块化。

scoped属性的实现原理是给每个dom元素添加了一个独一无二的动态属性,给css选择器额外添加一个对应的属性选择器,来选择组件中的dom。

<template>
    <div class="box">dom</div>
</template>
<style lang="scss" scoped>
.box{
    background:red;
}
</style>
复制代码

vue将代码转译成以下:

.box[data-v-11c6864c]{
    background:red;
}
<template>
    <div class="box" data-v-11c6864c>dom</div>
</template>
复制代码

scoped样式穿透

scoped虽然避免了组件间样式污染,可是不少时候咱们须要修改组件中的某个样式,可是又不想去除scoped属性。

  1. 使用/deep/
//Parent
<template>
<div class="wrap">
    <Child />
</div>
</template>

<style lang="scss" scoped>
.wrap /deep/ .box{
    background: red;
}
</style>

//Child
<template>
    <div class="box"></div>
</template>
复制代码
  1. 使用两个style标签
//Parent
<template>
<div class="wrap">
    <Child />
</div>
</template>

<style lang="scss" scoped>
//其余样式
</style>
<style lang="scss">
.wrap .box{
    background: red;
}
</style>

//Child
<template>
    <div class="box"></div>
</template>
复制代码

ref的做用

  1. 获取dom元素this.$refs.box
  2. 获取子组件中的datathis.$refs.box.msg
  3. 调用子组件中的方法this.$refs.box.open()

computed和watch区别

1.当页面中有某些数据依赖其余数据进行变更的时候,可使用计算属性computed。

computed.png

<template>{{fullName}}</template>
export default {
    data(){
        return {
            firstName: 'xie',
            lastName: 'yu fei',
        }
    },
    computed:{
        fullName: function(){
            return this.firstName + ' ' + this.lastName
        }
    }
}
复制代码

2.watch用于观察和监听页面上的vue实例,若是要在数据变化的同时进行异步操做或者是比较大的开销,那么watch为最佳选择。

watch.png

<template>{{fullName}}</template>
export default {
    data(){
        return {
            firstName: 'xie',
            lastName: 'xiao fei',
            firstName: 'xie xiao fei'
        }
    },
    watch:{
        firstName(val) {
            this.fullName = val + ' ' + this.lastName
        },
        lastName(val) {
            this.fullName = this.firstName + ' ' + val
        }
    }
}
复制代码

vue路由有几种模式

  1. hash模式
  2. history模式

组件之间的传值通讯

  1. 父组件给子组件传值经过props
  2. 子组件给父组件传值经过$emit触发回调
  3. 兄弟组件通讯,经过实例一个vue实例eventBus做为媒介,要相互通讯的兄弟组件之中,都引入eventBus
//main.js
import Vue from 'vue'
export const eventBus = new Vue()

//brother1.vue
import eventBus from '@/main.js'
export default{
	methods: {
	    toBus () {
	        eventBus.$emit('greet', 'hi brother')
	    }
	}
}

//brother2
import eventBus from '@/main.js'
export default{
    mounted(){
        eventBus.$on('greet', (msg)=>{
            this.msg = msg
        })
    }
}
复制代码

axios拦截器怎么配

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求以前作些什么
    return config;
}, function (error) {
    // 对请求错误作些什么
    return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据作点什么
    return response;
  }, function (error) {
    // 对响应错误作点什么
    return Promise.reject(error);
  });
复制代码

4、浏览器

浏览器渲染机制

  1. 构建DOM树(parse):渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node
  2. 构建渲染树(construct):解析对应的CSS样式文件信息
  3. 布局渲染树(reflow/layout):从根节点递归调用,计算每个元素的大小、位置等,给出每一个节点所应该在屏幕上出现的精确坐标;
  4. 绘制渲染树(paint/repaint):遍历渲染树,使用UI后端层来绘制每一个节点。

重绘和重排的区别

重绘(repaint或redraw):当盒子的位置、大小以及其余属性,例如颜色、字体大小等都肯定下来以后,浏览器便把这些原色都按照各自的特性绘制一遍,将内容呈如今页面上。重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性从新绘制,使元素呈现新的外观。

重绘发生在元素的可见的外观被改变,但并无影响到布局的时候。好比,仅修改DOM元素的字体颜色(只有Repaint,由于不须要调整布局)

重排(重构/回流/reflow):当渲染树中的一部分(或所有)由于元素的规模尺寸,布局,隐藏等改变而须要从新构建, 这就称为回流(reflow)。每一个页面至少须要一次回流,就是在页面第一次加载的时候。

触发重排的条件:任何页面布局和几何属性的改变都会触发重排:

  • 页面渲染初始化(没法避免)
  • 添加或删除可见的DOM元素
  • 元素位置的改变,或者使用动画
  • 元素尺寸的改变——大小,外边距,边框
  • 浏览器窗口尺寸的变化
  • 填充内容的改变,好比文本的改变或图片大小改变而引发的计算值宽度和高度的改变

重排一定会引起重绘,但重绘不必定会引起重排。

几种请求方法

GET、POST、HEAD、PUT、DELETE、CONNECT、OPTIONS、TRACE

get和post区别

请求方式 GET POST
参数位置 参数拼接到url的后面 参数在请求体中
参数大小 受限于浏览器url大小,通常不超过32K 1G
服务器数据接收 接收1次 根据数据大小,可分屡次接收
适用场景 从服务器端获取数据 向服务器提交数据
安全性 参数携带在url中,安全性低 相对于GET请求,安全性更高

如何解决跨域

  1. CORS
  2. jsonp
  3. 服务器代理

更多CORS请看完全读懂前端跨域CORS

JSONP原理

因为浏览器的同源策略限制,不容许跨域请求;可是页面中的 script、img、iframe标签是例外,不受同源策略限制。

Jsonp 就是利用script标签跨域特性进行请求。

JSONP 的原理就是,先在全局注册一个回调函数,定义回调数据的处理;与服务端约定好一个同名回调函数名,服务端接收到请求后,将返回一段 Javascript,在这段 Javascript 代码中调用了约定好的回调函数,而且将数据做为参数进行传递。当网页接收到这段 Javascript 代码后,就会执行这个回调函数。

JSONP缺点:它只支持GET请求,而不支持POST请求等其余类型的HTTP请求。

缓存的理解

缓存分为强缓存和协商缓存。强缓存不过服务器,协商缓存须要过服务器,协商缓存返回的状态码是304。两类缓存机制能够同时存在,强缓存的优先级高于协商缓存。当执行强缓存时,如若缓存命中,则直接使用缓存数据库中的数据,再也不进行缓存协商。

  1. 强缓存
  • Expires
  • cache-control
  1. 协商缓存
  • Last-Modified 和 If-Modified-Since
  • Etag 和 If-None-Match

更多缓存内容请看前端也要懂Http缓存机制

XSS和CSRF区别

  1. 跨站脚本攻击(Cross Site Scripting),为了避免和层叠样式表 CSS 混淆,故将跨站脚本攻击缩写为 XSS。恶意攻击者往 Web 页面里插入恶意 Script 代码,当用户浏览该页之时,嵌入其中 Web 里面的 Script 代码会被执行,从而达到恶意攻击用户的目的。

  2. 跨站请求伪造(Cross-site request forgery),是伪造请求,冒充用户在站内的正常操做。咱们知道,绝大多数网站是经过 cookie 等方式辨识用户身份,再予以受权的。因此要伪造用户的正常操做,最好的方法是经过 XSS 或连接欺骗等途径,让用户在本机(即拥有身份 cookie 的浏览器端)发起用户所不知道的请求。

区别:

  • 原理不一样,CSRF是利用网站A自己的漏洞,去请求网站A的api;XSS是向目标网站注入JS代码,而后执行JS里的代码。
  • CSRF须要用户先登陆目标网站获取cookie,而XSS不须要登陆
  • CSRF的目标是用户,XSS的目标是服务器
  • XSS是利用合法用户获取其信息,而CSRF是伪形成合法用户发起请求

HTTP与HTTPS的区别

  • HTTP的URL由http://起始且默认使用端口80,而HTTPS的URL由https://起始且默认使用端口443
  • HTTP是超文本传输协议,信息是明文传输,HTTPS则是具备安全性的 SSL 加密传输协议
  • HTTP的链接很简单,是无状态的,HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 http 协议安全

HTTP状态码

1xx表示客户端应该继续发送请求

2xx表示成功的请求

  • 200表示OK,正常返回信息
  • 201表示请求成功且服务器建立了新的资源
  • 202表示服务器已经接受了请求,但还未处理

3xx表示重定向

  • 301表示永久重定向,请求的网页已经永久移动到新位置
  • 302表示临时重定向
  • 304表示自从上一次请求以来,页面的内容没有改变过

4xx表示客户端错误

  • 401表示服务器没法理解请求的格式
  • 402表示请求未受权
  • 403表示禁止访问
  • 404表示请求的资源不存在,通常是路径写错了

5xx表示服务器错误

  • 500表示最多见的服务器错误
  • 503表示服务器暂时没法处理请求

5、性能优化

  • 使用CDN
  • gzip压缩
  • 文本压缩
  • 合并请求
  • 雪碧图
  • 图片懒加载
  • 缓存资源
  • 减小DOM操做

更多前端资料请关注公众号【前端壹读】。整理不易,且看且珍惜。

若是以为写得还不错,请关注个人掘金主页。更多文章请访问谢小飞的博客

PS:看到评论区好多同窗批评我说整理得太简单了,react,webpack,Promise都没有,怎么能算面试题呢?首先感谢你们的评论,我会更加努力整理深刻的知识点,其次,前端的东西多而杂,我整理这篇文章花了大概一个月时间,有些基础的知识点我可能工做了一段时间都没有用到过,因此偏向基础一点,请技术大佬忽略本文。

更多内容待续。。。

参考

flex

CSS清除浮动

圣杯布局和双飞翼布局的理解与思考

一图秒懂函数防抖和函数节流

web前端面试总结

公司要求会使用框架vue,面试题会被问及哪些

30道Vue面试题

总结了17年初到18年初百场前端面试的面试经验

面试分享:两年工做经验成功面试阿里P6总结

相关文章
相关标签/搜索