1、做接口前后端联调如何分析是前端还是后端问题
答:
2、cookies,sessionStorage和localStorage都有什么区别
答:
3、箭头函数和function普通函数之间有什么区别?
答:
4、常见的SPA首屏优化方式有哪些?
答:
大家基本都会采用服务器ssr渲染,路由懒加载。
首屏优化的核心是加载和解析的性能。
加载优化:
减少http请求,合理使用缓存,再快的网速,再大的并发数都不如直接跳过请求。
启用CDN加速:让不同地区的人都可以享受稳定可靠的下载速度
静态资源分域,将图片,音视频等静态资源放到不同的域名,防止加载时受浏览器并发数限制
DNS预解析,浏览器通过查询系统hosts或者进一步询问本地的DNS服务器就可以获得结果,但是也可能要经历完整的寻址过程:览器缓存-系统缓存-路由器缓存-ISP DNS缓存-递归搜索。DNS解析所需的时间差异非常大,延迟范围可以从1ms(本地缓存结果)到普遍的几秒钟时间。所以利用DNS预解析是有意义的。最明显的例子,DNS预解析在某个页面中包含非常多的域名非常有效,如搜索结果页。如何使用X-DNS_prefetch-Control: on|off,on:启用DNS预解析。
尽量启用http2
解析优化
资源体验优化:雪碧图,压缩图片,字体,音视频等文件的体积
按需加载:
使用骨架屏
5、VueX的重要核心属性有哪些?
答:五大核心属性:
6、什么是跨域?一般怎么解决跨域问题?
答:浏览器的同源策略的三大要素:协议相同、域名相同、端口 相同;同源三要素有一项不符合就是跨域。解决跨域的方法有:通过jsonp,或者通用代理服务器的方法通过本地代理转发。
7、Vue中v-if和v-show的共同点和不同点有哪些?
答:相同点:都能控制元素的显示隐藏.不同点:v-show本质是通过控制display:none;v-if是动态的向DOM树中添加或删除DOM元素,v-if更适合带有权限的操作,v-show更适合日常使用。可以减少数据渲染。
8、vue有哪些优点?
答:
9、vue2.0与3.0的区别
答:
Vue2--------------vue3 beforeCreate -> setup() created -> setup() beforeMount -> onBeforeMount mounted -> onMounted beforeUpdate -> onBeforeUpdate updated -> onUpdated beforeDestroy -> onBeforeUnmount destroyed -> onUnmounted activated -> onActivated deactivated -> onDeactivated errorCaptured -> onErrorCaptured
10、为什么最好把link放在head之间?
答:第一:规范要求;第二:从页面渲染原理来说,CSS的解析和html的解析需要同时进行,CSS的解析不会阻塞页面渲染。html解析得到的dom树需要css解析的样式规则,然后通过加流重绘计算后交给GPU负责合并图层生成页面。所以在不阻塞的情况下,你是选择串行还是并行呢,有什么更好的理由不让放head呢?第三:如果不放head会出现:一些浏览器会阻止渲染导致页面不能逐步呈现,没有样式或者空白不利用户体验。
11、说一下CSS选择器有哪些?
答:元素,id,类,分组,兄弟元素,伪类,属性,通配,复合,子元素,后代元素选择器
12、ES5数据结构中Set和Map有什么区别?
答:set可以用于数组去重,因为set值唯一,而map不唯一,map存储的是键值对,可以通过get方法取值而set不行,set存储的是值
13、为什么要封装axios?
答:封装之后,相当于给axios给出规范,使用起来更加简单,调用 方式统一,利于代码的管理和维护
14、js中bind,call,apply之间有什么区别?
答:三者都是重定义对象中的this:call跟apply绑定完this会立即调用当前的函数,apply传入的参数必须是数组,bind通常绑定完this返回不会立即调用当前函数,而是将函数返回。
15、什么是回流和什么是重绘?什么情况下使用?
回流:也有称重排,当渲染树节点发生改变,影响了节点的几何属性(如宽、高、内边距、外边距、或是float、position、display:none;等等),导致节点位置发生变化,此时触发浏览器重排(reflow),需要重新生成渲染树。
重绘:渲染树节点发生改变,但不影响该节点在页面当中的空间位置及大小。譬如某个div标签节点的背景颜色、字体颜色等等发生改变,但是该div标签节点的宽、高、内外边距并不发生变化,此时触发浏览器重绘(repaint)
注意:回流必将引起重绘,而重绘不一定会引起回流。
何时回引起回流?
1、添加或者删除可见的DOM元素;2、元素位置改变——display、float、position、overflow等等;3、元素尺寸改变——边距、填充、边框、宽度和高度4、内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;5、页面渲染初始化;6、浏览器窗口尺寸改变——resize事件发生时;
如何避免回流?
1、将动画效果应用到position属性为absolute或fixed的元素上,否则会引起父元素及后续元素频繁回流。
2、避免频繁操作DOM树,可以先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。
3、避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
16、Vue组件间是如何通信的?
1、父子组件间通信;父向子传递数据是通过 props,子向父是通过 events( e m i t ) ; 通 过 父 链 / 子 链 也 可 以 通 信 ( emit);通过父链 / 子链也可以通信( emit);通过父链/子链也可以通信(parent / c h i l d r e n ) ; r e f 也 可 以 访 问 组 件 实 例 ; p r o v i d e / i n j e c t A P I ; children);ref 也可以访问组件实例;provide / inject API; children);ref也可以访问组件实例;provide/injectAPI;attrs/ l i s t e n e r s ( listeners( listeners(attrs与 l i s t e n e r s 是 两 个 对 象 , listeners 是两个对象, listeners是两个对象,attrs 里存放的是父组件中绑定的非 Props 属性, l i s t e n e r s 里 存 放 的 是 父 组 件 中 绑 定 的 非 原 生 事 件 。 ) 2 、 兄 弟 通 信 B u s ; V u e x 3 、 跨 级 通 信 B u s ; V u e x ; p r o v i d e / i n j e c t A P I 、 listeners里存放的是父组件中绑定的非原生事件。) 2、兄弟通信Bus;Vuex 3、跨级通信Bus;Vuex;provide / inject API、 listeners里存放的是父组件中绑定的非原生事件。)2、兄弟通信Bus;Vuex3、跨级通信Bus;Vuex;provide/injectAPI、attrs/$listeners
17、vuex有哪些辅助函数,都有什么作用
vuex中提供了一些非常方便的辅助函数,比如mapState、mapGetter、mapMutation、mapAction等。
mapGetters和mapState用法一样,通过简单的…mapState([‘userName’])来代替比较长的计算属性函数在computed中调用即可。
mutations和actions返回的是函数,所以应该放在组件的methods属性中。
18、document.load与document.ready的区别?
load是页面加载完成后(包括所有的资源DOM文档树,css文件,js文件,图片资源)执行的一个函数;
ready是页面DOM树加载完成(不包括CSS,图片)执行的一个函数;
19、Vue的常见修饰符有哪些,各有什么作用?
Vue的常见修饰符:
事件修饰符:
.stop 阻止事件继续传播
.once 事件将只会触发一次
.prevent 阻止标签默认行为
.native可以理解为该修饰符的作用就是把一个 Vue 组件转化为一个普通的 HTML 标签(
.passive当我们在监听元素滚动事件的时候,会一直触发 onscroll 事件,在 PC 端是没啥问题的,但是在移动端,会让我们的网页变卡,因此我们使用这个修饰符的时候,相当于给 onscroll 事件整了一个 .lazy 修饰符。
表单修饰符:
v-model.lazy 转化为change事件再同步
v-model.number转化为数字内型
v-bind修饰符
.sync能对props进行一个双向绑定
.prop通过自定义属性存储变量,避免暴露数据,防止污染 HTML 结构;
20、javascript如何检测一个字符串类型?
JS数据类型主要分为两大类:基本数据类型和引用数据类型
基本数据类型:number、string、boolean、null、undefined、symbol(es6)
引用数据类型:object(array、function、date…)
1)typeof str == “string”:typeof 一般用来判断基本数据类型,除了判断null会输出"object",其它都是正确的,typeof 判断引用数据类型时,除了判断函数会输出"function",其它都是输出"object"
2)instanceof 可以准确的判断引用数据类型,它的原理是检测构造函数的prototype属性是否在某个实例对象的原型链上
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log({} instanceof Object);
3)constructor(构造函数):null和undefined是无效的对象,所以他们不会有constructor属性!
4) Object.prototype.toString.call()
Object.prototype.toString.call(‘’) ; // [object String]
Object.prototype.toString.call(1) ; // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); // [object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; // [object global] window 是全局对象 global 的引用
21、js中new操作符做了什么事情
new操作符的主要作用是产生对象。通过new创建空对象,为创建对象打基底,开辟了内存,将this 指针指向这个对象。
22、javascript如何实现继承,有什么优缺点?
JavaScript常见的继承方式:
1)原型链继承
function Parent() {
this.name = 'parent1';
this.play = [1, 2, 3]
}
function Child() {
this.type = 'child2';
}
Child.prototype = new Parent();
let child1 = new Child()
console.log(child1) // Parent { type: 'child2' }
console.log(child1.name) // parent1
优点:不仅能继承父类的实例属性和方法,还能继承原型属性或者方法
缺点:父类的引用属性被共享了,改动一处其他的也会被改
2)构造函数继承(借助 call)
function Parent2(){
this.name = 'parent1';
this.age = '18';
}
Parent2.prototype.getName = function () {
return this.name;
}
function Child(){
Parent2.call(this);
this.type = 'child'
}
let child = new Child();
console.log(child); // 没问题, Child { name: 'parent1', age: '18', type: 'child' }
console.log(child.getName()); // 会报错 child.getName is not a function
优点:父类的引用属性不会被共享,优化了第一种继承方式的弊端
缺点:但是只能继承父类的实例属性和方法,不能继承原型属性或者方法
3)组合继承
前面我们讲到两种继承方式,各有优缺点。组合继承则将前两种方式继承起来
function Parent3 () {
this.name = 'parent3';
this.play = [1, 2, 3];
}
Parent3.prototype.getName = function () {
return this.name;
}
function Child3() {
// 第二次调用 Parent3()
Parent3.call(this);
this.type = 'child3';
}
// 第一次调用 Parent3(), 原型链继承
Child3.prototype = new Parent3();
// 手动挂上构造器,指向自己的构造函数
Child3.prototype.constructor = Child3;
var s3 = new Child3();
var s4 = new Child3();
s3.play.push(4);
console.log(s3.play, s4.play); // 不互相影响,[ 1, 2, 3, 4 ] [ 1, 2, 3 ]
console.log(s3.getName()); // 正常输出'parent3'
console.log(s4.getName()); // 正常输出'parent3'
这种方式看起来就没什么问题,方式一和方式二的问题都解决了,但是从上面代码我们也可以看到Parent3 执行了两次,造成了多构造一次的性能开销
4)原型式继承:Object.create方法实现普通对象的继承
let parent4 = {
name: “parent4”,
friends: [“p1”, “p2”, “p3”],
getName: function() {
return this.name;
}
};
let person4 = Object.create(parent4)
5)寄生组合式继承
class Person {
constructor(name) {
this.name = name
}
// 原型方法
// 即 Person.prototype.getName = function() { }
// 下面可以简写为 getName() {...}
getName = function () {
console.log('Person:', this.name)
}
}
class Gamer extends Person {
constructor(name, age) {
// 子类中存在构造函数,则需要在使用“this”之前首先调用 super()。
super(name)
this.age = age
}
}
const asuna = new Gamer('Asuna', 20)
asuna.getName() // 成功访问到父类的方法,Person: Asuna
寄生组合式继承,借助解决普通对象的继承问题的Object.create 方法,在前面几种继承方式的优缺点基础上进行改造,这也是所有继承方式里面相对最优的继承方式
23、改变this指针的方向
1)call、apply、bind三者为改变this指向的方法
call
function fn(a,b,c){
console.log(this,a+b+c); // this指向window
}
fn();
fn.call(document,1,2,3);//call改变之后this指向document
//输出 #document 6 1,2,3是实参 结果相加为6
fn.apply(document,[1,2,3]); //apply
let ff = fn.bind('小明',1,2,3); //手动调用一下
call、apply与bind区别:前两个可以自动执行,bind不会自动执行,需要手动调用
call、bind与apply区别:前两个都有无数个参数,apply只有两个参数,而且第二个参数为数组
24、JS中同步和异步执行顺序
JavaScript语言是单线程,就意味着所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。同步任务指的是:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。异步任务指的是,不进入主线程、而进入任务队列(task queue)的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
25、keep-alive属性及生命周期
生命周期 用的是激活(activated)/停用(deactivated)。如何解决keep-alive缓存:第一种:使用会将数据保留在内存中;第二种:beforeRouteLeave(to, from, next) {
// 设置下一个路由的 meta
to.meta.keepAlive = false;
// C 跳转到 A 时让 A 不缓存,即刷新
next();
},第三种每次组件渲染的时候,都会执行beforeRouteEnter
beforeRouteEnter(to, from, next){
next(vm=>{
console.log(vm)
// 每次进入路由执行
vm.getData() // 获取数据
})
},
26、webpack代码分隔的实现
1)多入口打包2)动态引入
27、遍历数组的方法?
1) indexOf() 遍历数组,返回元素在数组中第一次出现的下标,两个参数,第一个是要查找的元素,第二个是开始查找的下标
2) forEach() 遍历数组获取每一个元素,没有返回值;
3)map() 遍历数组,返回一个新数组,数组由参数里的返回值组成.必须使用return.
4) filter() 遍历数组,返回一个新数组:新数组由参数里,条件为true的元素组成
5)some() 遍历数组,返回参数函数里符合条件的元素,只要检测到有一个元素符合条件就return.
6)reduce() 遍历数组, 返回参数函数里的返回值.一般作为累加器计算总价
7) every() 遍历数组,判断数组元素是否全部符合函数参数里的条件,全部满足返回true,否则false.
8)for of 遍历数组/字符串
前端学习群,需要的要我jjljzh