HTML
1.H5新特性有哪些?
- 语义化标签
- nav header footer aside section
- audio 、video、canvas、内联svg
- Web存储:LocalStorage、SessionStorage
- 表单
- 新的input类型:email、number、url、search、color、tel、date
- 新的表单属性:
- form新属性:autocomplete、novalidate
- input新属性:placeholder、required、min与max、height与width、autofocus等
2.对HTML语义化的理解
- 语义化是指根据内容的类型,在指定的地方用指定的标签,头部用herader,尾部用footer,导航用nav
- HTML语义化让页面的结构更清晰,有助于
浏览器和搜索引擎解析对内容的抓取 - 语义化的HTML在没有CSS的情况下也能保持很清晰的内容结构与代码结构
- 更利于SEO
3.Doctype有什么作用?
- DOCTYPE是一种标准通用标记语言的文档类型声明
- 作用:告诉浏览器的解析器(标准通用标记语言解析器),应该是用什么文档类型定义解析文档
- 影响:DOCTYPE不存在或格式不正确,会导致文档以兼容模式呈现
CSS
1.C3新特性有哪些?
- 圆角、边框背景、盒子阴影、字体阴影
- 渐变、过渡、旋转、帧动画
- 弹性布局
2.垂直居中的办法有哪些?
- 弹性布局 align-items:center
- Line-height 等于height (行高等于高度,一般用于文字垂直居中)
- Position:absolute (绝对定位+偏移值 top:50% margin-top:-50%)
- Position:absolute(绝对定位+偏移值0 + margin:0 auto)
- transform:translate(-50%,-50%)
3.清除浮动的方法有哪些,使用原因?
-
原因:解决父元素因为子元素浮动引起的内部高度为0的问题
-
方法:
-
父级div定义height
- 原理:父级div手动定义height,解决父级div无法自动获取高度问题
- 缺点:只适合高度固定的布局
-
结尾处加空div标签,
clear:both- 原理:在浮动元素后面添加一个空的div兄弟元素,利用css提高的
clear:both清除浮动,让父级div能自动获取到高度 - 缺点:如果页面浮动布局多,则需添加很多空div
- 原理:在浮动元素后面添加一个空的div兄弟元素,利用css提高的
-
父级div定义 伪类:after和zoom
/*清除浮动代码*/ .clearfix:after{ content:""; display:block; visibility:hidden; height:0;//必设,否则该元素会比实际高出若干像素 line-height:0; clear:both; } .clearfix{zoom:1}- 兼容性:IE8以上和非IE浏览器才支持
:after - 原理:与
clear:both的类似,zoom(IE私有属性)可解决ie6、7的浮动问题 - 推荐使用,建议定义公共类,减少css代码
- 兼容性:IE8以上和非IE浏览器才支持
-
父级div定义
overflow:hidden或auto- 超出盒子部分会被隐藏,不推荐使用
-
双伪元素法
.clearfix:before,.clearfix:after {/*伪元素是行内元素 正常浏览器清除浮动方法*/ content:""; display: block; clear: both; } .clearfix { zoom: 1;/*ie6清除浮动的方式 *号只有IE6-IE7执行,其他浏览器不执行*/ }
-
4.如何理解盒子模型
- 每个HTML元素都是一个盒子,这个盒子中可能又包裹着其他的盒子,这就是盒子模型
- 分类:
- 标准盒模型:外边距+边框+内边距+内容(宽高)
- IE盒模型:外边距+内容(宽高+内边距+边框)
- 设置:
- 标准盒模型:
box-sizing:content-box(默认) - IE盒模型:
box-sizing:border-box
- 标准盒模型:
5.BFC是什么,触发的情况
- 定义:块级格式上下文,规定内部的Block Box如何布局
- 触发的情况:
- 根元素,为html
- float的值不为none(默认)
- overflow的值不为visible(默认)
- display的值为inline-block、table-cell、table-caption时
- position的值为absolute或fixed
6.CSS选择器有哪些?
- id选择器
- class类选择器
- 标签选择器
- 属性选择器
- 后代选择器
- 子代选择器
- 并集选择器
- 伪类选择器
- 伪元素选择器
7. CSS样式权重优先级是怎么计算的?
!important>行内样式>id>class=伪类=属性>标签>*>继承
8. position几个属性的作用
9. 移动端的边框0.5px,怎么实现?
- 伪类缩放:【 :after 1px 然后 transform:scale(0.5)】
10. flex有哪些属性?以及值
-
flex-direction:决定主轴的方向
row(默认值):主轴为水平方向,起点在左端。row-reverse:主轴为水平方向,起点在右端。column:主轴为垂直方向,起点在上沿。column-reverse:主轴为垂直方向,起点在下沿。
-
flex-wrap:如果一条轴线排不下,如何换行。默认情况下,项目都排在一条线(又称"轴线")上。
nowrap(默认):不换行。wrap:换行,第一行在上方。wrap-reverse:换行,第一行在下方。
-
flex-flow:是flex-direction
属性和flex-wrap属性的简写形式,默认值为row nowrap-
flex-flow: <flex-direction> || <flex-wrap>;
-
-
justify-content:定义了项目在主轴上的对齐方式
flex-start(默认值):左对齐flex-end:右对齐center: 居中space-between:两端对齐,项目之间的间隔都相等。space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
-
align-items:定义项目在交叉轴上的对齐方式
flex-start:交叉轴的起点对齐。flex-end:交叉轴的终点对齐。center:交叉轴的中点对齐。baseline: 项目的第一行文字的基线对齐。stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
-
align-content:定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用
flex-start:与交叉轴的起点对齐。flex-end:与交叉轴的终点对齐。center:与交叉轴的中点对齐。space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。stretch(默认值):轴线占满整个交叉轴。
11. flex:1
那三个属性设置的什么值
-
flex是flex-grow、flex-shrink、flex-basis的缩写,默认值为0 1 auto。后两个属性可选-
该属性有两个快捷值:
auto(1 1 auto) 和 none (0 0 auto)。flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ] -
flex-grow:定义项目的放大比例,默认为0。即如果存在剩余空间,也不放大
-
flex-grow: <number>; /* default 0 */
-
-
flex-shrink:定义项目的缩小比例,默认为1。即如果空间不足,该项目将缩小
-
负值无效
-
flex-shrink: <number>; /* default 1 */
-
-
flex-basis:定义了在分配多余空间之前,项目占据的主轴空间(main size)
-
浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为
auto,即项目的本来大小 -
flex-basis: <length> | auto; /* default auto */
-
-
当 flex 取值为一个非负数字,则该数字为 flex-grow 值,flex-shrink 取 1,flex-basis 取 0%,如下是等同的:
.item {flex: 1;}
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
}
12. ::before和:after中双冒号和单冒号的区别?这两个伪元素的作用?
- 区别:
- 单冒号:伪类的书写
- 伪类:虚拟类名,有类似选择器的功能
:link :hover :active :visited :focus :first-child- 为了兼容旧版本样式,:after和::after有一样的作用
- 双冒号:伪元素的书写
- 伪元素:虚拟元素,有
- 类似dom结构的功能
::before ::after
- 单冒号:伪类的书写
- 作用:
::before:在当前元素的内容的前面插入一个子元素。插入的元素为内联元素:after:在当前元素的内容的后面插入一个子元素。
JS
1. 闭包是什么,应用场景,优缺点
- 定义:有权访问一个函数内部变量的函数
- 优缺点
- 优点
- 减少全局变量
- 减少传递函数的参数量
- 封装
- 缺点
- 会占有内存资源
- 过多的使用闭包会导致内存溢出
- 解决内存溢出问题:把不需要的变量,但是垃圾回收又收不走的变量赋值为null,然后让垃圾回收走
- 优点
- 应用场景:
- 函数防抖
- 函数节流
- 变量持久化(闭包中的变量不会被回收)
2. Promise是什么?
- 定义:Promise是一种异步编程的解决方案,是一种容器,保存着某个未来才会结束的事情的结果(通常是异步操作)
- 作用:解决回调地狱
- Promise创建后就会立即执行(指new Promise()),.then方法只有2个参数(resolve成功、reject失败)
- 常用方法:
- .then .catch .all .finally
3. JS的执行机制是什么?
- JS是单线程语言,一次只能执行一个任务,所有的任务都需要排队,排队的队列为:事件循环Event Loop,所有Event Loop就是js的执行机制
- js单线程
- js作为浏览器脚本语言,主要用来与用户进行交互,需要进行dom操作
- js是单线程,避免了同时操作DOM的矛盾
4. JS为什么需要异步?
- js是单线程语言,所以任务都需要排队,一次只能执行一个任务,如果上一个任务执行时间很长,后面的任务就必须一直处于等待状态
- 如果js不存在异步,只能从上往下执行,如果任务执行时间长,就会造成线程阻塞,导致用户体验很差,所以js需要异步
5. JS任务队列是什么?
- 任务队列就是一个事件队列,其中最重要的是异步任务事件和定时任务事件
- 异步任务事件(在某一个时刻才会被触发)
- 点击事件的回调函数
- 定时任务事件
- setInterval setTimeout
- 异步任务事件(在某一个时刻才会被触发)
6. JS的同步任务和异步任务,理解?
- 同步任务
- 在主线程执行栈上排队执行的任务,只有前一个执行完毕,才能执行后一个
- 异步任务
- 不进入主线程执行栈,而是进入“任务队列”中的任务,只有在同步任务执行完之后,才会执行异步任务
7. 理解 宏任务和微任务
- 宏任务与微任务都是异步任务,都是在同一个任务队列中,主要区别在于它们的执行顺序
- 在异步任务队列下 ,又分为宏任务队列与微任务队列
- 当一个宏任务执行结束之前,会在微任务队列执行栈中查找是否有微任务,如果有则执行,没有则开启一个新的宏任务,所以微任务总是在宏任务结束之前执行的
- 宏任务
- 整体script,setTimeout,setInterval,setImmediate
- 微任务promise MutationObserver
8. JS组成
- ECMAScript+DOM+BOM
9. DOM事件流的3个阶段分别是什么?
从上到下再从下到上
- 捕获阶段->目标阶段->冒泡阶段
10. 面向对象的特征是什么?
- 封装性
- 隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。
- 继承性
- 提高代码复用性;继承是多态的前提。
- 多态性
- 提高代码复用性;继承是多态的前提。
11. JS继承方式有哪些
- 方式:
- 构造函数继承
- 原型链继承
- 寄生继承
- 组合继承
- 寄生组合式继承(记住)
- 一般使用组合继承
- 通用属性:写在构造函数中
- 通用方法:写在原型中
12. call,apply,bind的用法以及区别?
-
用法
-
call
call 方法第一个参数是要绑定给this的值,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向window
-
var arr = [1, 2, 3, 89, 46] var max = Math.max.call(null, arr[0], arr[1], arr[2], arr[3], arr[4])//89 //理解: obj1.fn() obj1.fn.call(obj1); fn1() fn1.call(null) f1(f2) f1.call(null,f2)
-
-
apply
apply接受两个参数,第一个参数是要绑定给this的值,第二个参数是一个参数数组。当第一个参数为null、undefined的时候,默认指向window。
-
var arr = [1,2,3,89,46] var max = Math.max.apply(null,arr)//89 //理解: obj1.fn() obj1.fn.apply(obj1); fn1() fn1.apply(null) f1(f2) f1.apply(null,f2)
-
-
bind
和call很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。
bind返回值是函数
var obj = { name: 'Dot' } function printName() { console.log(this.name) } var dot = printName.bind(obj) console.log(dot) // function () { … } dot() // Dotbind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。而原函数 printName 中的 this 并没有被改变,依旧指向全局对象 window。
//参数的使用: function fn(a, b, c) { console.log(a, b, c); } var fn1 = fn.bind(null, 'Dot'); //fn1 方法的实参实则是在 bind 中参数的基础上再往后排 fn('A', 'B', 'C'); // A B C fn1('A', 'B', 'C'); // Dot A B fn1('B', 'C'); // Dot B C fn.call(null, 'Dot'); // Dot undefined undefined call 是把第二个及以后的参数作为 fn 方法的实参传进去
-
-
区别
-
事实上apply 和 call 的用法几乎相同, 唯一的差别在于:当函数需要传递多个变量时, apply 可以接受一个数组作为参数输入, call 则是接受一系列的单独变量
-
bind返回对应函数, 便于稍后调用; apply, call则是立即调用。
-
在 ES6 的箭头函数下, call 和 apply 将失效, 对于箭头函数来说:
箭头函数体内的 this 对象, 就是定义时所在的对象, 而不是使用时所在的对象;所以不需要类似于var _this = this这种丑陋的写法 箭头函数不可以当作构造函数,也就是说不可以使用 new 命令, 否则会抛出一个错误 箭头函数不可以使用 arguments 对象,,该对象在函数体内不存在. 如果要用, 可以用 Rest 参数代替 不可以使用 yield 命令, 因此箭头函数不能用作 Generator 函数,什么是Generator函数可自行查阅资料,推荐阅读阮一峰Generator 函数的含义与用法,Generator 函数的异步应用
-
-
实现bind方法
if (!Function.prototype.bind) { Function.prototype.bind = function () { var self = this, // 保存原函数 context = [].shift.call(arguments), // 保存需要绑定的this上下文 args = [].slice.call(arguments); // 剩余的参数转为数组 return function () { // 返回一个新函数 self.apply(context, [].concat.call(args, [].slice.call(arguments))); } } }
13. JS的设计模式有哪些?
- 设计模式的目的
- 为了更好的代码重用性,可读性,可靠性,可维护性
- 9种模式:学习
- 工厂模式*
- 单例模式*
- 适配器模式
- 装饰器模式
- 代理模式
- 外观模式
- 观察者模式*
- 迭代模式
- 状态模式
14. JS是高级语言吗?
- js是脚本语言,主要是作用于浏览器,与用户进行交互
15. JS的理解,优缺点
- js是一门跨平台脚本语言,主要作用于浏览器上,进行用户交互
- 优点
- 既可以面向过程又可以面向对象
- 是一门弱类型语言,编程更加随性
- 缺点
- 隐式类型转换混乱
- ==双等运算符自动转换数据类型的隐患
16. JS有哪些内置对象
- Object,Array,Boolean,Number,String
- Symbol,Map,Set,Promise,Proxy(ES6新增)
17. 使用JS时,遇到过的坑?
- 1· 获取DOM的时候提示无法获取
- 原因是:我把JS文件放在了head标签中,而HTML是从上到下顺序执行,所以就拿不到DOM
- 解决办法是:在script标签中添加defer=‘true’属性,延迟加载,或者把JS放到body之后
- 2· 在使用new Data设置日期格式的时候,发现无论怎么设置月份都会+1
- 原因是:JS中的月份从0开始
- 解决办法:把月份-1
18. 实现对象的深拷贝
- 使用JSON.parse(JSON.stringify(obj))
- 递归遍历 ,判断是否是Object
19. js解决异步的方案
- Promise
- async await
20. 作用域链
- 定义:内部环境可以通过作用域链来访问外部环境的属性和方法,但是,外部环境不能访问内部环境的任何属性和方法。注意,只能通过定义函数来延长作用域链条。
- 作用:查找标识符。当作用域需要查询变量的时候会沿着作用域链依次查找,如果找到标识符就会停止搜索,否则将会沿着作用域链依次向后查找,直到作用域链的结尾
21. 原型链
- 原型:所有的函数都有一个特殊的属性
prototype(原型),prototype属性是一个指针,指向的是一个对象(原型对象),原型对象中的方法和属性都可以被函数的实例所共享。所谓的函数实例是指以函数作为构造函数创建的对象,这些对象实例都可以共享构造函数的原型的方法。 - 原型链:
- 定义:每一个对象都有一个原型,原型也是对象,那原型也有原型,这样就形成了一个链式结构,成为原型链。
- 作用:查找引用类型的熟悉,查找属性会沿着原型链依次进行,如果找到该属性会停止搜索并做相应的操作,否则将会沿着原型链依次查找直到结尾。
- 对象访问成员的访问规则: 如果对象访问某个成员,先看自己有没有,自己有就访问自己的,自己没有就访问原型的。如果原型也没有,就沿着原型链一直往上查找,直到找到为止,如果找到头了还没有找到,就返回undefined或者报错.
22. ES5实现Object.assign
23. 在JS中什么是伪数组?如何将伪数组转化为标准数组?
- 伪数组的特点:
- 按索引方式存储数据
- 具有length属性
- 没有数组的push、pop、shift、unshift等方法
- 分类
- function的arguments对象
- getElementsByTagName、ele.childNodes等返回的NodeList对象
- 自定义的某些对象
- 转化方法:
- 使用Array.prototype.slice.call()或[].slice.call()
- 使用ES6中Array.from()方法
24. 一个function,清除字符串前后的空格(兼容所有浏览器)
function trim(str){
if(str && typeof str === "string"){
return str.replace(/(^\s*)|(\s*)$/g/,"")//取出前后空白符
}
}
25. undefined与null的区别
- undefined:一个表示“无”的原始值
- null:表示尚未存在的对象
26. 如何实现浏览器的前进后退功能?
-
要求:当我们点开一系列页面例如a-b-c时,到c页面后退可以查看b、a页面,在b、a页面前进可以查看c页面,但是当在b页面重新进入一个新的页面时,此时再也不能通过前进或者后退进入c页面了,这是怎么实现的呢?
-
提供两个栈:Stack1、Stack2
-
- 进入一系列页面a、b、c:将a、b、c依次压入栈Stack1,此时在页面c
- 后退两步:将c、b依次弹出再压入栈Stack2
- 前进一步:将b从Stack2弹出压入Stack1
- 打开新的页面d:将d压入栈Stack1
- 清空Stack2,此时就不能通过前进或者后退进入c页面
27. 描述 new 一个对象的过程
-
代码
function Foo(name,age){ this.name = name; this.age = age; this.class = 'class-1'; // return this //默认有这一行 } var f = new Foo('张三',20) -
过程:
- 创建一个新对象
- this指向这个新对象
- 执行代码,即对this赋值
- 返回this
28. 对象方法
-
Object.keys(对象):将对象里面的键名提取出来返回成一个数组- 用途:空对象判断 Object.keys(obj).length==0
var obj={a:1,b:2} Object.keys(obj) ==== > [a,b] Object.values(obj) ==> [1,2] Object.entries(obj) ===> [[a,1],[b,2]] -
Object.values(对象):将对象里面的键值提取出来返回成一个数组 -
Object.entries(对象):将对象里面的键名与键值提取出来成一个新二维数组 -
for of:循环遍历数组和对象
let obj={a:1,b:2}; for(let [key,value] of Object.entries(obj)){ window.console.log(key,value); } //输出结果: //a 1 //b 2 -
Object.assign(目标对象,需要合并的对象1,需要合并的对象2)`
-
注:后面的对象的值会覆盖前面对象的值,也就是目标对象的值
-
let obj1 = { a: 1 } let obj2 = { b: 2, a: 3 } Object.assign(obj1, obj2) console.log(obj1);//{a:3,b:2} let a1={a:1}; let c1={a:3,b:2}; let b1={d:1,b:4}; window.console.log(Object.assign(b1,a1,c1));//{d:1,b:4,a:3}
-
29. 数组常用的方法
forEach、map、filter、
push、pop、shift、unshift
ES6
1.ES6新特性有哪些?
- 箭头函数 ()=>{}
- 匿名函数,不能用于构造函数,不能被new
- this指向上下文
- 模板字符串``
- 解构赋值
- 展开运算符...
- let const 关键字
- Promise
- class类
- for of
- 遍历数组中的每一项
- 与for in的区别
- 无法遍历对象
- 输出结果为数组的值,for in为数组的索引
- 不会遍历自定义属性(用.或[]添加的属性)
jQuery
1. jq中常用的api有哪些
-
$(selector).html():方法返回或者设置被选元素的内容,ps:在一定的程度上可以等同于value- 返回(跟value等同):$(selector).html()
- 设置:$(selector).html("world")
-
$(selector).attr():方法设置或者返回被选元素的属性值- 返回:$(selector).attr("属性名")
- 设置:$(selector).attr("属性名","值")
-
$(selector).addClass():向被选元素添加一个或者多个类,即class属性- $(selector).addClass("hello");
-
eval(String):执行括号内的表达式或者是语句必须为字符串
-
$(selector).each(function(index,element){}):遍历jQuery对象集合,在每个对象上执行function函数-
一般用法
$(selector).each(function(key){ alert($(selector)[key]); })
-
-
$(selector).data():方法向被选元素附加数据或者获取数据- 从被选元素中返回数据::$(selector).data(name);
- 向元素附加元素:
- $(selector).data(name,value);
- 对象:$(selector).data(Object);
Ajax
1.Ajax的工作原理是什么?
- 定义:Ajax是一种异步获取数据的技术
- 原理:通过XmlHttpRequest对象来向服务器发送异步请求,类似一个中间层,负责请求数据,而不影响浏览器其他事件的执行,等到数据回来之后再通知浏览器,浏览器在进行处理
2.Ajax的使用步骤
-
新建一个
XMLHttpRequest对象let xhr = new XMLHttpRequest() -
使用open和send方法发送请求
xhr.open('方法','url地址') //设置请求的方法和地址 xhr.send() //发送请求 -
使用onload注册回调
xhr.onload=function(){} -
根据服务器返回的结果做响应的处理
xhr.responseText
3.get和post有什么区别?
- 参数传输方式不同
- get通过url传输参数
- post通过请求体传输参数
- 安全性不同
- post通过请求体传输参数,安全性比较高
- get通过url传输参数,在历史记录,浏览器缓存很容易查到数据信息,所以安全性偏低
- 可传输参数大小不同
- post可以传输任意格式的参数
- get因为是在url中传输,有长度限制
4. ajax是怎么上传文件的?
- 使用FormData对象
- 1、创建一个FormData对象
let fd = new FormData()
- 2、通过files[0]获取到确认选择的图片信息
let imgInfo = document.getElementById('img').files[0]
- 3、把文件信息添加到FormData对象中
fd.append('img',imgInfo)- 注:键值对形式
- 4、在ajax请求的响应体中添加FormData对象
$ajax({data:fd})
- 1、创建一个FormData对象
5. 怎么封装axios?
把axios封装,创建一个新的请求对象,将项目基地址放进去,然后暴露出去,如果其他组件用到了就直接导入封装好的axios文件
Vue
1. Vue的生命周期钩子
-
所有的生命周期都是一个函数
-
书写位置:和methods是兄弟关系
-
特点:自动执行,不用调用
- beforeCreate:
- 创建前,它还不能访问data与methods
- 只自动执行一次
- created:
- 创建后,可以访问data与methods,但是还不能访问vue渲染后的dom
- 只自动执行一次
- 用途:进入页面的接口请求
- beforeMount:
- 渲染前,还没完成data与methods里面渲染到dom,还不能访问vue渲染后的dom
- 只会执行一次
- mounted:
- 渲染后,已完成data与methods的dom渲染,可以访问vue渲染后的dom
- 最早可以访问vue渲染后的dom的钩子
- 只会执行一次
- beforeUpdate:
- 更新前,数据(页面中使用的数据)已修改,但还没完成dom渲染
- 会执行多次
- updated:
- 更新后,数据已修改,且dom已完成渲染
- 会执行多次
- beforeDestroy:
- 销毁前,准备销毁当前组件,但是还没有完成销毁
- 只会执行一次
- destroyed:
- 销毁后,切断了页面的渲染,回到了渲染前,还可以访问data属性和methods方法,还可以做一些善后工作,但是不能访问vue渲染后的dom
- 只会执行一次
- activated:重新激活时调用,需要keep-alive触发
- deactivated:取消激活时调用,需要keep-alive触发
-
语法
new Vue({ el: '#app', methods: { }, beforeCreate(){//创建前,还不能访问data与methods}, created(){//创建后,能访问data与methods}, beforeMounte(){//渲染前,被vue管理的dom还没完成在vue实例内的渲染,所以还不能调用dom}, mounted(){//渲染后,被vue管理的dom已完成vue实例内的渲染,所以现在可以调用dom}, beforeUpdate(){//更新前,当数据发生改变,但页面还没完成更新时调用。}, updated(){//更新后,数据发生改变,且完成了页面更新时调用。} })
2. Vue中的传值方法有哪些?
-
父传子
- props
- 父组件
:属性名="值/处理值的方法" - 子组件
props:['属性名']
- 父组件
- $children
- props
-
子传父
-
$parent(在子组件中写)
-
$emit
- 子组件:$emit('属性名',值)
- 父组件:@属性名=“处理值的方法”
-
$refs(在父组件中写)
-
调用子组件的时候调用一个ref
<v-fgsheader ref="header"></v-fgsheader> -
在父组件中通过
this.$refs.header.属性 this.$refs.header.方法 -
可能出现的问题:子组件很多的时候,不知道传到哪个子组件里面
-
-
-
兄弟
- $parent 父搭桥通信
- $root 根组件搭桥通信
-
祖孙后代
-
provide 提供
// 祖孙 隔代传值 父级使用provide定义 provide() { return { apple: this.food, changeApple: this.changeApple }; }, // 这里的this指向父组件的实例 第二个成员changgeApple是一个可以修改apple的函数 -
inject 注入
inject: ["apple", "changeApple"], mounted() { // 通过this调用 this.changeApple("香蕉"); console.log(this); } // inject注入的数据会平铺到子组件的实例上,通过this可以调用
-
-
没有关系
-
$bus(广播传值)
-
新建一个bus.js文件,暴露vue实例
// 导入vue import Vue from 'vue'; // 暴露一个vue实例出去 export default new Vue() -
在要广播的地方引入刚才定义的实例
import bus from '../bus.js' -
传播:bus.$emit('名称','数据')
-
接收:bus.$on('名称',data=>{})
-
-
-
本地传值
-
localStorage
-
存:
localStorage.setItem('属性名',JSON.stringify(值)); -
取
var tolist = JSON.parse(localStorage.getItem('属性名'));
-
-
Vuex
-
-
路由传值
-
动态路由传值
//1. 配置路由 routes:[ //动态路由参数 以冒号开头 {path:'/user/:id',conponent:User} ] //2. 传值 第一种写法 : <router-link :to="'/user/'+item.id">传值</router-link> 第二种写法 : goToUser(id) { //'user' 是路径名称 this.$router.push({path:'/user/'+id}); } //3. 在对应页面取值 this.$route.params; //结果:{id:123} -
Get传值(类似HTMLGet传值)
//1. 配置路由 const routes = [{path:'/user',component:User},] //2. 传值 第一种写法 : <router-link :to="'/user/?id='+item.id">传值</router-link> 第二种写法 : goToUser(id) { //'user' 是路径名称 this.$router.push({path:'user',query:{ID:id}}); } //3. 在对应页面取值 this.$route.query; //结果 {id:123}注:路径传递参数会拼接在URL路径后
-
命名路由push传值
//1. 配置路由 const routes = [{path:'/user',name: 'User',component:User},] //2. 传值 goToUser(id) { //'User' 是路径重命名 this.$router.push({name:'User',params:{ID:id}}); } //3. 在对应页面取值 this.$route.params; //结果:{id:123}注:命名路由传递参数不在URL路径拼接显示
-
3. Vue的优缺点有哪些
- 优点
- 轻量 双向数据绑定 指令 插件化 渐进式灵活 组件系统 自底向上灵活应用 只关心数据 第三方整合 Vue全家桶
- 缺点
- vue应用是单页面应用,不利于seo优化,需要在服务端做seo
- 前进后退功能需要使用程序进行处理
- 初次加载耗时比较多,因为第一次加载就需要把所有的html css js加载完成
4. router和route的区别
- router:路由实例对象
- route:当前跳转路由信息对象
5. Vuex是什么?
-
vuex是专门为vue开发的状态管理工具,类似于一个仓库,仓库中存储着应用中的状态
-
vuex的状态存储是响应式的
-
改变状态的唯一方法就是提交commit(mutation),符合vue的单向数据流思想
-
vuex的模块
- state :保存状态
- getters:加工state成员给外界,(相当于vue的计算属性,有缓存)
- mutations:state成员操作。修改状态的方法,必须是同步
- action:异步操作。用于提交mutation ,不是直接改变状态,而是异步操作,或者一些比较复杂的逻辑都可以使用action提交dispatch ,dispatch就是commit
- module:模块化状态管理。保存特定的模块,例如用户模块,允许将单一的store拆分为多个并且各自保存
-
参考https://www.jianshu.com/p/2e5973fe1223
-
单向数据流:访问state,修改用mutations
6. vue中你常用的指令有哪些?
v-text、v-html、v-model、v-on、v-bind、v-if、v-for
- 改变标签内容
- v-text:替换当前标签的文本内容
v-text="一句话表达式"或{{值}},类似innerText
- v-html:替换当前标签的内容,并以html形式展示出来
v-html="一句话表达式"
- v-text:替换当前标签的文本内容
- 改变表单元素值
- v-model:实现表单元素值的双向绑定
v-model="变量"
- v-model:实现表单元素值的双向绑定
- 监听事件
- v-on:事件的绑定
v-on:事件名="需要执行的简单代码或方法"@事件名="需要执行的简单代码或方法"- 修饰符
.stop:阻止冒泡@事件名.stop="事件执行代码".prevent:阻止默认事件@事件名.prevent="事件执行代码".enter:回车才执行后面的方法或者js
- v-on:事件的绑定
- 改变标签样式与属性值
- v-bind
v-bind:属性名="属性值":属性名="属性值"
- v-bind
- 渲染列表数据
- v-for
- 数组:
v-for="(item,index) in array" - 对象:
v-for="(value,key,index) in object"
- 数组:
- v-for
- 条件渲染
- v-if:
v-if="boolean值",控制标签是否渲染 - v-else-if:
v-else-if="boolean值" - v-else
- v-if:
- 控制标签是否显示
- v-show:控制标签的显示和隐藏
- v-show="boolean值"
- v-show:控制标签的显示和隐藏
7. 你是怎么理解vue的单向数据流的?
- 单向数据流是指,在父子组件使用prop传值时,父组件的状态变更,数据会流向子组件,但是反过来则不行,不可以直接在子组件直接变更传递的props,这样会导致数据流不清晰,如果子组件可以修改props,那么就可能会出现无法分辨是哪一个子组件修改的这个状态了
- 如果子组件需要修改,可以在自己的data中定义保存props
8. 谈一谈你对keep-alive的理解
-
keep-alive是vue内置的一个组件
-
作用:缓存组件,避免在组件重新激活后再次渲染
-
用法:一般结合动态组件使用
<keep-alive> <login v-if="index == 0" /> </keep-alive> -
对应的两个生命钩子:
- activated:当组件激活时调用
- deactivated:当组件失活时调用(未激活)
-
提供include与exclude属性
- include:匹配名称的组件才会被缓存
- exclude:匹配名称的组件都不会被缓存
- 优先级:exclude > include
9. v-model的原理是什么?
-
本质:一个语法糖
将
<son v-model="msg" />翻译为<son :value="msg" @input="msg=$event"/> -
原理:input事件与value属性的绑定
-
当input事件触发,就会修改data中的值,data中的值发生改变就会渲染
-
app.vue<template> <div class="app"> <h3>app.vue</h3> <p>msg是:{{msg}}</p> <son :value="msg" @input="msg = $event"/> </div> </template> <script> import son from './son'; export default{ components:{ son }, data(){ return { msg:"hello" } } } </script> -
son.vue<template> <div class="son"> <input type="text" v-model="selfMsg" @input="toFather"> </div> </template> <script> export default{ //父传子 props:['value'], data(){ return{ selfMsg:this.value } }, watch:{ //父组件值变了,子组件的值也跟着改变 value(val){ this.selfMsg = this.fatherMsg } } methods:{ toFather(){ //传递值给父组件 this.$emit('input',this.selfMsg) } } } </script>
-
-
如果不是input元素(组件上),可以使用
model:{}(与data同级)来改变- prop:修改绑定的值
- event:修改事件名
/* 外面用我这个组件的时候,如果使用v-model,他会生成:value 我想外面生成的不再是:value,而是:v1 我希望外面用我这个组件的时候,如果使用v-model,默认生成@input就改成@xx */ model:{ // 告诉外面调用我组件时,如果写了v-model就会生成 :v1="绑定的值" prop:"v1", // 告诉外面调用我组件时,如果写了v-model就会生成 @xx="绑定值=$event" event:"xx" },- 默认情况下v-model生成的是:value 和 @input,如果要改就用上面的model代码来改属性名和事件名(这是加在子组件上)
-
官方v-model
-
app.vue<template> <div class="app"> <h3>app.vue</h3> <p>msg是:{{msg}}</p> <!--给子组件传值--> <son :value="msg" @input="msg = $event"/> </div> </template> <script> import son from './son'; export default{ components:{ son }, data(){ return { msg:"hello" } } } </script> -
son.vue<template> <div class="son"> <!--<input type="text" :value="value" @input="toFather($event)">--> <input type="text" :value="value" @input="$emit('input',$event.target.value)"> </div> </template> <script> export default{ //父传子 props:['value'],} }, methods:{ toFather(e){ //e是事件对象(原生事件) //传递值给父组件 this.$emit('input',e.target.value) } } } </script> -
修改默认绑定属性和事件
//app.vue里面 <son v-model="msg" /> //son.vue里面 <input type="text" :value="v1" @input="$emit('xx',$event.target.value)"> <script> export default{ //父传子 props:['v1'], //修改默认绑定属性和事件 model:{ prop:'v1', event:'xx' } } </script>
-
10. computed与watch有什么区别?
- 定义
- computed:计算属性,依赖于某个值而产生新的值
computed有缓存机制,只有当计算值变化才会返回内容,如果依赖的值不发生变化,就不需要重新计算- 数值运算时可使用
- watch:监听器,观察的作用,类似于数据监听的回调函数,一旦这个数据发送改变都会触发监听的回调
- 在数据发生变化时需要执行异步会开销比较大的操作时,就可以使用watch
- computed:计算属性,依赖于某个值而产生新的值
- 实现原理:
- 都是新增一个watcher
- computed是惰性求值的,默认没有set
11. vue的父组件和子组件的生命周期钩子的执行顺序?
- 父加载->子加载->子渲染->父渲染->
- 父beforeCreate -> 父created -> 父beforeMount -> 子beforCreate -> 子created -> 子beforMount -> 子mouted -> 父mouted
- 父更新之前 -> 子更新之前 -> 子更新 -> 父更新
- 父beforUpdate -> 子beforUpdate -> 子updated -> 父updated
- 父销毁之前 -> 子销毁之前 -> 子销毁 -> 父销毁
- 父beforDestroy -> 子beforDestroy -> 子destroyed -> 父destroyed
12. vue-router有几种模式?vue-router实现的原理是什么?
- 模式:3种
- hash:哈希模式
- 使用url中的hash值来做路由跳转路径,#号后面的都是哈希值
- history:历史模式
- 没有#号,需要后端配合,否则可能会出现静态资源无法加载的情况
- abstract:抽象模式
- 后端用的,node环境下使用的
- hash:哈希模式
- hash缺点:#后面的参数后端都无法获取到,服务器无法读取,因为是锚点
- 实现原理:
- hashchange监听url的变化,映射指定的组件并渲染
- window.onhashchange
- 当hash值(url上 #/xxx)发生改变触发
- 获取hash值:location.hash
- 路由切换原理(router-view):监听hash改变事件,在改变事件里获得hash,再根据hash值来找到组件对应的html代码,渲染到路由出口那
- window.onhashchange
- history:
- 通过H5提供(的History API来实现路由(push和pop实现的浏览器历史记录栈,.back(),.go())
- 刷新后页面空白:重新向后台请求当前url需要的静态资源,需要后端做静态资源的定位,进行url匹配,当满足
- hashchange监听url的变化,映射指定的组件并渲染
13. vue-router的导航守卫有哪些?路由的函数钩子?
- 全局守卫
beforeEach(to,from,next)全局前置守卫,路由跳转之前触发beforeResolve(to,from,next)全局解析守卫,在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用afterEach(to,from)全局后置钩子,路由跳转之后调用的回调函数
- 路由独享的守卫
beforeEnter(to,from,next),在路由配置上直接定义
- 组件内的守卫
beforeRouterEnter(to,from,next)在渲染该组件的对应路由被 confirm 前调用 ,不能使用this 获取组件实例beforeRouterUpdate(to,from,next)在当前路由改变,但是该组件被复用时调用 , 可以使用this获取组件实例beforeRouterLeave(to,from,next)导航离开该组件的对应路由时调用,可以使用this获取组件实例
14. vue实现双向绑定的原理?
-
核心是使用了Object.definProperty() vue3.0改为proxy
-
在初始化data(initData)时,会将data作为对象传递给监听器Observer,Observer会遍历data中的每一个key,包括深层嵌套的key(对象中的对象),在遍历的过程中会使用Object.definProperty为每一个key做数据拦截,设置get与set,当初次渲染时会触发get , 在get中收集依赖,数据变更时会触发set,set中会调用dep通知依赖(watcher)进行更新(update)
-
采用的是发布订阅的设计模式
-
vue2.0中object.definePropety遍历递归data对象里每个属性,重写set和get方法, 通过订阅器和订阅者做一个绑定. 重写操作数组的7个方法的原型. vue3.0里面用proxy代替了object.definePropety().不需要递归了
采用的是数据劫持结合发布和-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调
-
原理:用Object.defineproperty()重新定义(set方法)对象设置属性值和(get方法)获取属性值的操纵来实现的
- vue2.0:
Object.property(对象,属性名,属性描述符(对象))- 缺点:一次只能监听一个属性的改变
- vue3.0:
new Proxy(对象,{get(被操作的对象,属性名){},set(被操作的对象,属性名,赋值的值){}})- 注意:用了proxy对象代理后,要想触发set方法,必须通过proxy对象进行赋值
- vue2.0:
-
vue的数据双向绑定是通过数据劫持和发布-订阅者功能来实现的
-
实现步骤:
1.实现一个监听者Oberver来劫持并监听所有的属性,一旦有属性发生变化就通知订阅者
2.实现一个订阅者watcher来接受属性变化的通知并执行相应的方法,从而更新视图
3.实现一个解析器compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相对应的订阅者
-
流程图:
15. vue是如何实现对数组的数据监听的?
- 数组无法使用Object.definProperty, vue的方法是将可改变数组的7个方法进行劫持,并且重写了数组的原型
- 在每次触发这7个方法时,都会执行重写的原型,进行通知依赖更新
- push shift unshift pop splice sort reverse
16. proxy对比Object.definProperty的优势是什么?
- Proxy可以直接监听整个对象,而Object.definProperty需要递归遍历对象中的每一个成员
- Proxy可以直接监听数组,而Object.definProperty需要劫持数组的7个方法做数据响应和更新通知
17. 路由懒加载
18. v-for中,key的作用,为什么不建议使用index作为key
- **key的作用:**让vue更高效的进行虚拟DOM的更新
- **原理:**vue在patch过程中可以通过key精准的对比两个节点是否是同一个节点,从而避免频繁更新不同的元素,使整个patch过程更高效,减少dom的操作,提高性能。
- 原因:
- key是唯一的,可以是后端返回的数据中的id,或者其他的唯一数据
- 如果使用index作为key,那么顺序是不会变化的,即便重排了元素,也是会按照顺序来算,这样就不利于diff算法进行虚拟DOM节点比对
19. v-if与v-for谁的优先级更高?如何正确使用避免性能浪费?
- v-for的优先级更高,在指令解析源码中v-for优先于v-if编译
- 可以将v-if条件判断写在template上,先判断条件,再执行循环,这样就解决了性能浪费的问题
- 如果必须在同一个位置使用v-if v-for ,那么可以使用计算属性过滤掉不需要不符合条件的项,往往for循环中的数据都是可以渲染的
20. 如何实现动态路由的
21. MVC,MVP,MVVM是什么?
- MVC
- 传统的MVC是指,用户操作会请求服务端路由,路由会调用对应的控制器来处理,控制器会获取数据,再将结果返回给前端,前端手动进行页面重新进行渲染,通信是单向的
- M(Model模型【后端数据库】),V(view视图),C(controller控制器)
- 主要是基于分层目的,让彼此的职责分开
- View通过controller来联系Model,controller是View和Model的协调者,View和Model不直接联系,所以基本上通信都是单向的
- MVP
- M(Model模型),V(view视图),P(Presenter主持?)
- MVP是从MVC模式演变过来的,都是通过controller / presenter负责逻辑的处理 + Model提供数据 + View负责显示
- 在MVP中,Presenter完全把Model与View进行了分离,主要的程序逻辑在presenter中实现,并且presenter与view是没有直接关联的,是通过定义好的接口进行交互,从而使得view变更的时候可以保持presenter不变
- MVP模式的框架
- Riot.js
- MVVM
- 传统的前端会将数据手动渲染到页面上,MVVM模式下不需要用户手动操作DOM元素,而是将数据绑定到ViewModel层上,会自动将数据渲染到页面中,视图变化会通知ViewModel层更新数据,ViewModel就是MVVM模式的桥梁
- M(Model模型),V(view视图),VM(ViewModel)
- MVVM是双向的
- MVVM是把MVC里的Controller和MVP里的Presenter改成了ViewModel。Model+View+ViewModel
- View的变化会自动更新到ViewModel,ViewModel的变化也会自动同步到View上显示
- 这种自动同步是因为ViewModel中的属性实现了Observer,当属性变更时都能触发对应的操作。
- MVVM模式的框架
- AngularJS
- Vue
- React
22. vue页面渲染过程
23. vue中的$set是
浏览器相关
事件机制
跨域
1. 跨域是什么?
跨域是指浏览器为了安全做的同源策略,协议,域名,端口三者其中一种不同都是跨域
2. 为什么浏览器要使用同源策略
- 防止CSRF攻击(利用用户的登录态发起恶意请求)
- 跨域,ajax请求会失败(不能完全阻止CSRF)
3. 解决跨域的办法
- JSONP
- 利用script标签没有跨域限制的漏洞,并提供一个回调函数callback
- 缺点:只支持get
- CORS
- 需要浏览器和后端同时支持
- 浏览器端:自动进行CORS通信
- 服务端:设置
Access-Control-Allow-Origin就可以开启CORS
- 需要浏览器和后端同时支持
- document.domain
- postMessage
4. 了解预检请求
存储
1.登录保持是怎么实现的?
- 利用localStorage把服务端返回的token保存在本地,在接下来的请求的请求头中都携带上token,并在路由响应中判断,如果响应码为401则token失效,再根据对应的逻辑做处理
2. 说一说cookies,sessionStorage,localStorage的区别?
- 存储位置不同
- cookies:发送请求会自动携带cookies
- sessionStorage和localStorage:会保存在本地
- 大小不同
- cookies:数据不能超过4K
- sessionStorage和localStorage:有大小限制,比cookies大,可以达到5M或者更大
- 时效不同
- cookies:在设置的过期时间前一直有效
- sessionStorage:在浏览器窗口关闭后销毁
- localStorage:持久保存,只要不手动删除都会一直存在
3. 如何让cookies在浏览器关闭就失效?
- 不对cookies设置任何过期时间,不是任何正、负或者0的时间即可
4. 如何让localStorage与cookies一样设置失效时间?
- 在存储数据时,存储一个时间戳,在get获取localStorage中的value时,拿当前时间戳与首次存入的时间戳做比较即可
缓存机制
性能优化
1. 谈一谈你对浏览器缓存机制的理解?
- 浏览器缓存一般都是针对静态资源,比如js,css,图片等等
- 缓存是一种简单高效的性能优化方式,可以显著的减少网络传输造成的影响,浏览器缓存一般会在 发起网络请求和浏览响应的时候进行性能优化
- 发起网络请求时:
- 浏览器会先查询请求头中对应的缓存数据,如有存在,就会拦截本次网络请求并且返回缓存数据的副本,并且结束本次网络请求
- 浏览器响应时:
- 如果命中缓存,但是缓存已经过期了,那么浏览器会继续发送本次请求,但是会在请求头中加上if-none-match字段,让服务端判断请求的数据有没有变化,如果没有变化服务端就会返回304 not modified ,浏览器刷新缓存,然后将缓存的副本返回
- 发起网络请求时:
- 缓存策略
- 强制缓存
- 强制缓存不需要重新发送请求(浏览器缓存中存在请求的数据)
- 协商缓存
- 发送请求验证请求资源是否需要更新(浏览器里有缓存,但是请求过期了,问一下服务器要不要更新数据)
- 如果没有更新服务器返回304 ,浏览器刷新缓存并返回缓存副本
- 如果需要更新,服务端直接返回最新的数据给浏览器
- 发送请求验证请求资源是否需要更新(浏览器里有缓存,但是请求过期了,问一下服务器要不要更新数据)
- 强制缓存
1. 缓存位置
2. 缓存策略
3. 实际场景应用缓存策略
渲染原理
兼容性问题
1. 不同浏览器的标签默认的外补丁(margin)和内补丁(padding)不同
解决方案:css里增加通配符*{margin:0;padding:0}
2. IE6双边距问题;在IE6中设置了float,同时又设置margin,就会出现边距问题
解决方案:设置display:inline;
3. 当标签的高度设置小于10px,在IE6、IE7中会超出自己设置的高度
解决方案:超出高度的标签设置overflow:hidden,或者设置line-height的值小于你的设置高度
4. 图片默认有间距
解决方案:使用float为img布局
5. IE9以下浏览器不能使用opacity
解决方案:
opacity:0.5;
filter:alfha(opacity=50);
filter:progid:DXlmageTransform.Microsoft.Alfha(style=0,opacity=50);
6. 边距重叠问题;当相邻两个元素都设置了margin边距时,margin将取最大值,舍弃最小值;
7. cursor:hand显示手型在safari上不支持
解决方案:统一使用cursor:pointer
8. 两个块级元素,父元素设置了overflow:auto;子元素设置了position:relative;且高度大于父元素,在IE6、IE7会被隐藏而不是溢出;
解决方案:父级元素设置position:relative
9. const问题
说明:
- Firefox下,可以使用const关键字来定义常量;
- IE下,只能使用var关键字来定义常量。
解决方法:统一使用var关键字来定义常量。
10. event.srcElement问题
问题说明:
- IE下,event对象有srcElement属性,但是没有target属性;
- Firefox下,event对象有target属性,但是没有srcElement属性。
解决方法:使用srcObj = event.srcElement?event.srcElement:event.target;
11. 事件绑定
- IE:dom.attachEvent();
- 其他浏览器:dom.addEventListener();
标准浏览器采用事件捕获的方式对应IE的事件冒泡机制(即标准由最外元素至最内元素或者IE由最内元素到最外元素)最后标准方亦觉得IE这方面的比较合理,所以便将事件冒泡纳入了标准,这也是addEventListener第三个参数的由来,而且事件冒泡作为了默认值。
12. 操作tr的html
在ie9以下,不能操作tr的innerHTML
13. ajax略有不同
- IE:ActiveXObject
- 其他:xmlHttpReuest
14. 对象宽高赋值问题
问题说明:FireFox中类似obj.style.height = imgObj.height的语句无效。
协议
1.Http请求状态码有哪些?
- 1** 信息,服务器收到请求,需要请求者继续执行操作
- 2** 成功,操作被成功接收并处理
- 3** 重定向,需要进一步的操作
- 4** 客户端错误,请求包含语法错误或无法完成请求
- 5** 服务器错误,服务器在处理请求的过程中发生错误
- 常见的如下:
- 200 请求成功
- 301 资源或网页等被永久转移到其他的URL
- 404 请求的资源或网页不存在
- 401 权限不足
- 403 服务器拒绝
- 500 服务器内部错误
2.http请求方式有哪些?
- get、post、put、delete、head、trace
3.请求报文与响应报文你了解吗?
- 请求报文:3部分组成
- 请求行:包含请求方法,请求地址url,协议版本
- 请求头:包含请求的附加信息,键值对的形式,Authorization
- 请求体:浏览器发送给服务器的数据(参数)
- 响应报文:3部分组成
- 响应行:包含协议版本,状态码,状态描述
- 响应头:content-type
- 响应体:服务器返回的数据
xhr.responseText
4.HTTP与HTTPS的区别
- 概念:
- HTTP:网络上应用最广泛的一种网络协议,是客户端与服务端通信的标准(TCP),HTTP是明文传输的
- HTTPS:以安全为目标的HTTP通道,即在HTTP下加入了SSL协议,用于对HTTP协议传输进行加密(HTTPS是HTTP的安全版)
- 区别:
- HTTPS需要申请证书,需要收费
- HTTP是超文本传输协议,信息是明文传输,HTTPS是具有安全性的SSL加密传输协议
- HTTP使用的端口是80,HTTPS使用的端口是443
- HTTP是无状态链接的,HTTPS则需要进行身份认证
5.TCP3次握手和4次挥手
优化
1. 你做过哪些性能优化
- 减少HTTP请求
- 懒加载:图片、路由、长列表数据
- 外部资源使用CDN引入
- 功能相似的组件与逻辑抽离并复用
- 函数防抖、函数节流
- 减少js代码的全局变量,html标签语义化
2. 你是怎么做小程序优化的?
- 避免频繁的操作setData,如果不需要更新视图,直接使用this
- 分页懒加载,避免使用setData传输大数据
- 除开tabBar外,其他的图片都从服务器加载
- 清理没有用到的代码和资源,减少包的大小
场景
1. 网站崩了怎么办?
2. 网页从输入网址到渲染完成经历了哪些过程?
大致可分为七步:
1、输入网址
2、发送到DNS服务器,并获取域名对应的web服务器对应的ip地址
3、与web服务器建立tcp连接
4、浏览器向web服务器发送http请求
5、web服务器响应请求,并返回指定url的数据
6、浏览器下载web服务器返回的数据并解析html源文件
7、生成Dom树,解析js和css,渲染页面
3. 哪些操作会造成内存泄漏?
-
常见的内存溢出:
- 不再需要用到一个函数后,它的定时器没有停止clearTimeout()
- 一个DOM被删除前,没有解绑事件
- 一个DOM被删除前,对它的引用没有手动清除掉
- 临时创建的DOM没有被手动清除掉
- 闭包没有管理好,大量闭包的使用
- 意外的全局变量引起的内存泄漏
-
内存泄漏:一段内存用完了,我们已经不需要它了。但是它没有被释放掉(引用),所以这部分内存不能被重新利用,这部分内存就被浪费掉了。就像垃圾堆积占用了空间一样。
-
垃圾回收机制:JavaScript的垃圾回收机制依据的是引用计数,如果引用计数降为0,它就会被自动回收。
- 垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收。
-
避免内存泄漏、利用好垃圾回收机制的做法是:如果我们不需要一个东西,就要先把对于它的各种引用都摘除掉
4. 如何实现浏览器内多个标签页之间的通信?
-
调用localStorage
-
在一个标签页里面使用
localStorage.setItem(key,value)添加(修改、删除)内容; -
在另一个标签页里面监听
storage事件。window.addEventListener("storage", function(event){ console.log(event.key + "=" + event.newValue); }); -
即可得到
localstorge存储的值,实现不同标签页之间的通信。
-
-
调用cookies+setInterval()
-
将要传递的信息存储在cookie中,每隔一定时间读取cookie信息,即可随时获取要传递的信息。
-
存储在cookies中:
document.cookie="name="+name; -
定时读取:
<script type="text/javascript"> $(function(){ function getCookie(key) { return JSON.parse("{\"" + document.cookie.replace(/;\s+/gim,"\",\"").replace(/=/gim, "\":\"") + "\"}")[key]; } setInterval(function(){ console.log("name=" + getCookie("name")); }, 10000); }); </script>
-
5. 比如用循环渲染了一堆P标签,但是P标签没更新,怎么办?
$forceUpdate()强更新
6. 如果后台管理系统中 点击侧边栏,右上角出现×怎么解决
7. sourcetree中你跟你同事的代码不兼容怎么办?
- 暂存自己的代码,提交到本地仓库
- 进行pull操作,从远程仓库拉取,sourceTree会将两个人的相同的文件进行合并
- 再次提交到本地仓库,也就是merge
- 进行push操作,将合并后的代码推送到远程仓库