HTML5部分

HTML5新特性有哪些

  1. Canvas绘图以及SVG绘图
  2. 语义化标签(header、nav、footer、article、section)
  3. 音频、视频(audio、video)API
  4. 拖放(Drag and drop)API
  5. 地理定位(Geolocation)
  6. 本地离线存储(localStorage),长期存储数据,关闭浏览器后不丢失。
  7. 会话储存(sessionStorage),数据在关闭浏览器后自动删除。

cookie与sessionStorage和localStorage的区别

  1. 保存方式

    cookie存放在客户的浏览器上。

    session都在客户端中保存,不参与服务器通讯。

  2. 生命周期

    cookie可设置失效时间

    localStorage除非手动清除否则永久保存

    sessionStorage关闭当前页面或浏览器关闭后失效

  3. 存储的大小

    cookie 4kb

    session 5M

  4. 共同点

    不能存储其他数据类型,只能存储字符串数据类型

    如果一定要存储其他数据类型,转成 json 格式存储

  5. 使用方法

1
2
3
4
5
var storage = null;
storage.setItem("key","value") //调用setItem方法存储数据
storage.getItem("key") //调用getItem方法获取key的值
stroage.removeItem("key") //删除key对应的值
stroage.clear() //清空数据

BFC

BFC(Block Formatting Context),即块级格式化上下文,它是页面中一个独立的容器,容器中的元素不会影响到外面的元素。

触发条件

触发BFC的条件包含不限于:

  • 根元素,即HTML元素
  • 浮动元素:float值为left、right
  • overflow值不为 visible,为 auto、scroll、hidden
  • display的值为inline-block、inltable-cell、table-caption、table、inline-table、flex、inline-flex、grid、inline-grid
  • position的值为absolute或fixed

CSS部分

CSS选择器的优先级排序

选择器类型

选择器 表现形式
id #id,例如:id=“name”,id=“password”
class .class,例如:class=“name”,class=“password”
标签 例如:body、div、p、ul、li
属性 [type=‘text’]
伪类 :hover,例如:链接样式,a元素的伪类,有4种不同的状态:link、visited、active、hover。
相邻选择器、子代选择器 +、>,例如:div > p,带大于号 ’>’
通配符选择器 *

!important > 行内样式 > id选择器 > 类选择器 || 伪类选择器 || 属性选择器 > 标签选择器 || 伪元素选择器 > 通配符选择器 || 子选择器 || 相邻选择器 > 继承样式

1
2
3
4
5
6
7
* 第零等:!important,大过了其它任何设置。
* 第一等:代表内联样式,如:style='',权值为1000。
* 第二等:代表ID选择器,如:#content,权值为0100。
* 第三等:代表类、伪类和属性选择器,如.content,权值为0010。
* 第四等:代表标签选择器和伪元素选择器,如<div> <p>,权值为0001。
* 第五等:通配符、子选择器、相邻选择器等的。如*、>、+,权值为0000。
* 第六等:继承的样式没有权值,通配选择器定义的规则优先级高于元素继承过来的规则的优先级。

垂直居中DIV

请看这里css之div盒子居中常用方法

清除浮动

  1. 父级盒子添加overflow方法

    优点:简单、代码少、浏览器支持好

    缺点:内容被隐藏掉,无法显示需要溢出的元素,不能和position配合使用

  2. 使用after伪元素清除浮动:

    用法:给浮动元素父级增加 .clearfix::after(content: ‘’; display: table; clear: both;)

    优点: 符合闭合浮动思想,结构语义化正确,不容易出现怪问题

    缺点: 由于IE6-7不支持:after,使用zoom:1

  3. 父级盒子定义height:

    优点: 简单、代码少。

    缺点:只适合高度固定的布局,要给出精确的高度

  4. 额外标签法:

    用法: 在浮动元素后使用一个空元素,并在 CSS 中赋予.clear{clear:both;}属性即可清理浮动。

    优点: 通俗易懂,书写方便。

    缺点: 添加许多无意义的标签,结构化比较差。

盒子模型

  1. 盒模型由内容(content)、内边距(padding)、边框(border)、外边距(margin)组成。

  2. 盒模型分为IE盒模型和W3C标准盒模型。

  3. W3C标准盒模型又叫content-box,元素宽度/高度由border+padding+content组成。

    (属性width,height只包含内容content,不包含border和padding)

  4. IE盒模型又叫border-box,元素宽度/高度由content组成。

    (属性width,height包含border和padding,指的是content+padding+border。)

padding和margin的区别

  • margin是盒子的外边距,即盒子与盒子之间的距离,而padding是内边距,是盒子的边与盒子内部元素的距离。
  • margin是用来隔开元素与元素的间距;padding是用来隔开元素与内容的间隔
  • margin用于布局,可以分开元素,使元素与元素互不相干;padding用于设置元素与内容之间的间隔,让内容(文字)与(包裹)元素之间有一段“呼吸距离”。

有哪些方式可以隐藏页面元素?区别?

通过css实现隐藏元素方法有如下:

  • display:none
  • visibility:hidden
  • opacity:0
  • 设置height、width模型属性为0
  • position:absolute
  • clip-path
display: none visibility: hidden opacity: 0
页面中 不存在 存在 存在
重排 不会 不会
重绘 不一定
自身绑定事件 不触发 不触发 可触发
transition 不支持 支持 支持
子元素可复原 不能 不能
被遮挡的元素可触发事件 不能

重绘和重排是什么?如何避免?

  1. 重排:当DOM的变化影响了元素的几何信息(元素的的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。
  2. 重绘:当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,所以重绘跳过了创建布局树和分层的阶段。
  3. 重排需要重新计算布局树,重绘不需要,重排必定发生重绘,但是涉及到重绘不一定要重排
  4. 触发重排的方法: 页面初始渲染、添加/删除可见的DOM元素、改变元素位置、改变元素尺寸、改变元素内容、改变元素字体大小、改变浏览器窗口尺寸、设置 style 属性的值等。
  5. 避免重排的方式:样式集中改变、使用 absolute 或 fixed 脱离文档流。

CSS中有哪些长度单位?

  1. 绝对长度单位:px
  2. 百分比: %
  3. 相对父元素字体大小单位: em
  4. 相对于根元素字体大小的单位: rem
  5. 相对于视口*宽度的百分比(100vw即视窗宽度的100%): vw
  6. 相对于视口*高度的百分比(100vh即视窗高度的100%): vh

JavaScript和ES6部分

ES6新特性?

  1. 新增块级作用域,let定义变量和const定义常量
  2. 变量的解构赋值
  3. 箭头函数(=>)
  4. 扩展运算符(…)
  5. 模块(import/export)
  6. 类(class/extends)
  7. Promise
  8. Proxy
  9. Symbol
  10. Set数据结构,类似于数组,但是成员的值都是唯一的,没有重复的值
  11. includes()用于判断数组是否包含给定的值 返回一个布尔值
  12. find()用于找出第一个符合条件的数组成员
  13. findindex()返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1

Set和Map的区别

  1. Map是键值对,Set是值的集合,键和值可以是任何的值
  2. Map可以通过get方法获取值,而Set不能因为它只有值,Set只能用has来判断,返回一个布尔值
  3. Set的值是唯一的可以做数组去重,Map由于没有格式限制,可以做数据存储

闭包的理解和使用场景

  1. 理解:闭包就是函数中包含另一个函数,可以让你在函数外部读取到内部的变量(就是在函数内部再定义一个函数),让这些变量的值始终保持在内存中,可以达到延长变量生命周期的效果,过多使用会导致内存泄漏的问题。
  2. 优点:可以避免全局变量造成污染。
  3. 缺点:闭包会常驻内存,增加内存使用量,使用不当会造成内存泄漏。
  4. 特征:(1)函数嵌套函数。(2)在函数内部可以引用外部的参数和变量。(3)参数和变量不会以垃圾回收机制回收。
  5. 使用场景:(在创建私有变量和想延长变量的生命周期时会用到闭包)

JS获取HTML DOM元素的方法

  • 通过ID获取(getElementById)
  • 通过name属性(getElementsByName)
  • 通过标签名(getElementsByTagName)
  • 通过类名(getElementsByClassName)
  • 获取html的方法(document.documentElement)
  • 获取body的方法(document.body)
  • 通过选择器获取一个元素(querySelector)
  • 通过选择器获取一组元素(querySelectorAll)

事件捕获和事件冒泡

  1. 事件捕获:事件从文档根节点流向目标节点,途中会经过目标节点的各个父级节点,并在这些节点上触发捕获事件,直至到达事件的目标节点。
  2. 事件冒泡:与事件捕获相反,事件会从目标节点流向文档根节点,途中会经过目标节点的各个父级节点,并在这些节点上触发捕获事件,直至到达文档的根节点。整个过程就像水中的气泡一样,从水底向上运动。
  3. event.stopPropagation() 可以阻止事件流的进一步传播。

注意:stopPropagation()会阻止事件捕获和事件冒泡,但是无法阻止标签的默认行为,例如点击链接任然可以打开对应网页。

Var、 let 、const 区别?

  1. 变量提升:

    var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined

    letconst不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错

  2. 暂时性死区:

    var不存在暂时性死区

    letconst存在暂时性死区,只有等到声明变量的那一行代码出现,才可以获取和使用该变量

  3. 块级作用域:

    var不存在块级作用域

    letconst存在块级作用域

  4. 重复声明:

    var允许重复声明变量

    letconst在同一作用域不允许重复声明变量

  5. 修改声明的变量:

    varlet可以

    const声明一个只读的变量,一旦声明,就不能改变了

  6. 使用:

    能用const的情况尽量使用const,其他情况下大多数使用let,避免使用var

== 和 ===区别

  • 相等操作符(==)会做类型转换,再进行值的比较,全等运算符(===)不会做类型转换
1
2
let result1 = ("123" === 123); // false,不相等,因为数据类型不同
let result2 = (123 === 123); // true,相等,因为数据类型相同值也相同
  • nullundefined 比较,相等操作符(==)为 true,全等为 false
1
2
let result1 = (null == undefined ); // true
let result2 = (null === undefined); // false
  • 相同点:都是判定两个是否相等
    不同点:== 只比较不比较类型,而 ===会判断类型

什么是防抖和节流?

  1. 防抖:n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

    应用场景:提交按钮、用户注册时候的手机号验证、邮箱验证

  2. 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效

    应用场景:射击游戏中的mousedown、keydown事件,文字输入、自动完成的keyup事件

电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖

电梯第一个人进来后,15秒后准时运送一次,这是节流

原型,原型链 ?

  1. 原型:每个函数对象都有一个 prototype 属性,这个属性就是函数的原型对象

  2. 原型链:当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数prototype,如果还没有找到就会再在构造函数prototype__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链

  3. 注:原型链的形成是真正是靠__proto__而非prototype

深拷贝浅拷贝的区别?

  • 浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

  • 深拷贝:将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。

总而言之,浅拷贝改动拷贝的数组原数组也会变(慎用!项目中很多地方共用的数组都会变)。深拷贝修改新数组不会改到原数组。

浅拷贝

  1. Object.assign()
  2. 函数库lodash的 _.clone 方法
  3. es6的展开运算符
  4. Array.prototype.concat()
  5. Array.prototype.slice()

深拷贝

  1. JSON.parse(JSON.stringify())
  2. 函数库lodash的 _.cloneDeep 方法
  3. jQuery.extend()方法
  4. 手写递归方法

经典案例:

  1. 数组和对象,都是浅拷贝
  2. 解构(…)数组是深拷贝一层,对于一维的数组是深拷贝,多维的只能算是浅拷贝
1
2
3
4
5
6
7
8
9
10
11
<script>
let arr = [1, 2, 3]
let newArr = [...arr]
newArr.push(4)
console.log("就一层深拷贝:", arr , newArr) // [1,2,3] [1,2,3,4]

let arr2 = [[1, 2, 3], [4, 5, 6]]
let newArr2 = [...arr2]
newArr2[0].push(888)
console.log('这里是二维数组,解构就不是深拷贝了', arr2, newArr2) // [[1,2,3], [4,5,6,888]] [[1,2,3], [4,5,6,888]]
</script>

JavaScript中的数据类型?

  1. 基本类型
  • Number:数值,包括整型和浮点型。
  • String:字符型。
  • Undefined:未定义,声明变量时未赋值。
  • Null:定义为空或者不存在。
  • Boolean:布尔值,true or false。
  • Symbol:独一无二的值。
  1. 引用数据类型
  • Object:对象。
  • Array:数组。
  • Function:函数。

Promise

  1. 含义异步编程的一种解决方案,用来解决回调地狱
  2. 三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)
  3. resolved函数作用:将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved)。
  4. reject函数的作用:将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected)。
  5. Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

GET和POST的区别

  • 后退/刷新:GET无害,POST数据会被重新提交。
  • 数据:GET一般是用来获取数据,POST提交数据。
  • 数据类型:GET只允许ASCII字符,POST无限制。
  • 数据大小:GET大小有限制(一般来说1024字节),POST理论上来说没有大小限制。
  • 安全性:GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  • 可见性:GET参数通过URL传递对所有人可见,POST数据不可见。
  • 历史保留:GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  • 书签:GET产生的URL地址可以被收藏为书签,而POST不可以。

数组常用方法

  • push() 接收任意数量的参数,并将它们添加到数组末尾
  • unshift() 开头添加
  • concat() 方法用于连接两个或多个数组。

实例:

1
2
3
4
var hege = ["Cecilie", "Lone"];
var stale = ["Emil", "Tobias", "Linus"];
var kai = ["Robin"];
var children = hege.concat(stale,kai);

children输出结果:

1
Cecilie,Lone,Emil,Tobias,Linus,Robin

  • pop() 删除数组的最后一项
  • shift() 删除数组的第一项
  • splice() 传入两个参数,分别是开始位置,删除元素的数量
  • slice() 可以用来从数组中提取元素,该方法不会改变元素数组,而是将截取到的元素封装到一个新数组返回

  • splice() 方法用于添加或删除数组中的元素。

实例:

1
2
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2,0,"Lemon","Kiwi");

fruits 的输出结果:

1
Banana,Orange,Lemon,Kiwi,Apple,Mango
参数 描述
index 必需。规定从何处添加/删除元素。 该参数是开始插入和(或)删除的数组元素的下标,必须是数字。
howmany 可选。规定应该删除多少元素。必须是数字,但可以是 “0”。 如果未规定此参数,则删除从 index 开始到原数组结尾的所有元素。
item1, …, itemX 可选。要添加到数组的新元素

  • indexOf() 返回要查找的元素在数组中的位置,如果没找到则返回 -1
  • includes() 返回要查找的元素在数组中的位置,找到返回true,否则false
  • find() 返回第一个匹配的元素

数组去重

  1. 利用ES6的**…new Set()**去重,最方便最简单
1
2
3
4
5
<script>
var A = [1,2,3,3,3,1,6,8,9,6]
// 利用ES6 Set去重,最简单最方便
console.log(...new Set(A)) // 1 2 3 6 8 9
</script>
  1. 利用双重循环和splice()来去重
1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
// 利用for循环和splice去重
for(i = 0; i < A.length; i++){
for(j = i+1; j < A.length; j++){
if(A[i] === A[j]){
A.splice(j,1)
// 删除之后,元素少了一个了,要减去1,重新遍历
j--;
}
}
}
console.log(A) // (6) [1, 2, 3, 6, 8, 9]
</script>
  1. 利用indexOf去重,indexOf() 返回要查找的元素在数组中的位置,如果没找到则返回 -1。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script>
var A = [1,2,3,3,3,1,6,8,9,6]
// 利用indexOf来去重
function unique(arr){
// 判断传过来的数据是不是数组,如果不是,控制台输出错误信息
// 如果不是数组,Array.isArray(arr)为false,用反号把它变为true
if(!Array.isArray(arr)){
console.log('类型错误,不是数组')
return
}
// 如果是数组,新建一个新的数组来作为去重的数组
var array = []
for(i = 0;i<arr.length;i++){
// 如果arr[i]不在新建的数组中,把它加进去,在就不加
if(array.indexOf(arr[i]) === -1){
array.push(arr[i])
}
}
// 将去重后的数组返回出去
return array
}
console.log(unique(A)) // (6) [1, 2, 3, 6, 8, 9]
</script>

注意:利用**includes()也和indexOf()**的方法差不多,includes() 返回要查找的元素在数>组中的位置,找到返回true,否则false

JS中new操作符有什么用?

  • 创建临时对象,并将this指向临时对象
  • 将构造函数的原型属性方法挂载到新对象的__proto__(原型指针)上
  • return 临时对象

排序方式

  1. 冒泡排序:比较所有相邻元素,如果第一个比第二个大,则交换它们。
  2. 选择排序:找到数组中的最小值,选中它并将其放置在第一位。
  3. 插入排序:从第二个数开始往前比,比它大就往后排。
  4. 归并排序:把数组劈成两半,再递归地对数组进行“分”操作,直到分成一个个单独的数。
  5. 快速排序:从数组中任意选择一个基准,所有比基准小的元素放到基准前面,比基准大的元素放到基准的后面。

Vue部分

数据双向绑定原理

  • 通过数据劫持结合发布-订阅模式,通过Object.defineProperty()为各个属性定义get、set方法,在数据发生改变时,给订阅者发布消息,触发相应的事件回调

Vue生命周期

  • 从创建、初始化数据、编译模板、挂载DOM、渲染-更新-渲染、卸载等一系列过程,称为为Vue 实例的生命周期。

Vue导航守卫的钩子函数有哪些

全局守卫:

  • router.beforeEach:全局前置守卫,进入路由之前
  • router.beforeResolve:全局解析守卫,在beforeRouteEnter调用之后调用
  • router.afterEach:全局后置钩子,进入路由之后

路由守卫:

  • beforeRouteEnter():进入路由前
  • beforeRouteUpdate():路由复用同一个组件时
  • beforeRouteLeave():离开当前路由时

组件之间如何传值

  1. Vue父子组件之间传值
  • 子组件通过props来接受数据和通过$emit来触发父组件的自定义事件;
  1. 兄弟组件之间的传值
  • 建一个公共组件bus.js.。传递方通过事件触发bus.$emit。接收方通过在mounted(){}生命周期里触发bus.$on
  1. 可以通过VUEX 来跨组件传参。

MVVM是什么

Model-View-ViewModel的缩写,把MVC中的Controller层变成ViewModel层,Model代表数据模型,View代表UI组件,MVVM实现了View层和Model层的自动同步,也即是我们不用手动操纵哦Dom元素

MVVM与MVC的区别有:

MVVM与MVC的最大区别就是:它实现了View和Model的自动同步,也就是当Model的数据改变时,我们不用再自己手动操作Dom元素,来改变View的显示,而是改变数据后该数据对应View层显示会自动改变。MVVM并不是用VM完全取代了C,ViewModel存在目的在于抽离Controller中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在Controller中实现

路由之间如何传参

  • 通过router-link路由导航跳转传递
1
<router-link to=`/a/${id}`>routerlink传参</router-link>
  • 跳转时使用push方法拼接携带参数。
1
2
3
this.$router.push({
path: `/index/${id}`,
})
  • 通过路由属性中的name来确定匹配的路由,通过params来传递参数。
1
2
3
4
5
6
this.$router.push({
name: 'index',
params: {
id: id
}
})
  • 使用path来匹配路由,然后通过query来传递参数。
1
2
3
4
5
6
this.$router.push({
path: '/index',
query: {
id: id
}
})

Route和router的区别

  1. router是VueRouter的一个对象,通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,包含了所有的路由包含了许多关键的对象和属性。例如history对象。
  • $router.push({path:’/path’}); 本质是向history栈中添加一个路由,在我们看来是 切换路由,但本质是在添加一个history记录
  • $router.replace({path:’/path’}); 替换路由,没有历史记录
  1. route是一个跳转的路由对象,每一个路由都会有一个route对象,是一个局部的对象,可以获取对应的name,path,params,query等。
  • $route.path
    字符串,等于当前路由对象的路径,会被解析为绝对路径,如 “/index/” 。
  • $route.params
    对象,包含路由中的动态片段和全匹配片段的键值对
  • $route.query
    对象,包含路由中查询参数的键值对。例如,对于 /index?id=1 ,会得到 $route.query.id == 1。

Vue 路由跳转方式

  • router-link 标签跳转
  • this.$router.push()
  • this.$router.replace()
  • **this.$router.go(n)**:(0:当前页,-1上一页,+1下一页,n代表整数)

Vue中key是用来做什么的?为什么不推荐使用index作为key?

  1. key的作用主要就是为了高效的更新虚拟DOM,使用key值,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素。它也可以用于强制替换元素/组件而不是重复的使用它。
  2. 当以数组的下标index作为index值时,其中一个元素(如增删改查)发生了变化就有可能导致所有元素的key值发生变化。

说出至少vue 3个常用事件修饰符?

.stop 阻止点击事件冒泡

.prevent 阻止默认事件

.once 只执行一次

.self 只在元素本身触发

vuex有哪几种属性

  1. state:vuex的基本数据,用来存储变量。
  2. mutation:提交更改数据,同步更新状态。
  3. action:提交mutations,异步操作。
  4. getter:是store的计算属性。
  5. modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。