前端面试秘籍(稳过面试)

211 阅读16分钟

JS

谈谈JS的垃圾回收机制

垃圾回收机制有两种方式,一种是引用法,一种是标记法

引用法

判断一个对象的引用数,引用数为0就回收,引用数大于0就不回收。

缺点:两个对象互相引用,各自引用数都是1,所以不会被回收,从而造成内存泄漏。

标记法

从window的指针开始,递归搜索子节点,并为其进行标记,直到所有子节点被遍历结束。那么没有被遍历到节点,也就没有被标记,也就会被当成没有被任何地方引用,就可以证明这是一个需要被释放内存的对象,可以被垃圾回收器回收。

事件循环(event loop)

JS是单线程的,为了防止一个函数执行时间过长阻塞后面的代码,所以会先将同步代码压入执行栈中,依次执行,将异步代码推入异步队列,异步队列又分为宏任务队列和微任务队列,因为宏任务队列的执行时间较长,所以微任务队列要优先于宏任务队列。微任务队列的代表就是,Promise.then,MutationObserver,宏任务的话就是setImmediate setTimeout setInterval

事件冒泡、捕获(委托)

  • 事件冒泡指在在一个对象上触发某类事件,如果此对象绑定了事件,就会触发事件,如果没有,就会向这个对象的父级对象传播,最终父级对象触发了事件。
  • 事件委托本质上是利用了浏览器事件冒泡的机制。因为事件在冒泡过程中会上传到父节点,并且父节点可以通过事件对象获取到目标节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方式称为事件代理
  • 事件委托的优点:

可以大量节省内存占用,减少事件注册,比如在ul上代理所有li的click事件就非常棒

可以实现当新增子对象时无需再次对其绑定(动态绑定事件)

阻止默认行为 return false e.preventDefault()

阻止冒泡事件 event.stopPropagation()

event.stopPropagation() 或者 ie下的方法 event.cancelBubble = true; //阻止事件冒泡

父节点怎么知道是那个子节点触发事件的? 用e.target判断


ES6新特性

\

  1. 新增symbol类型 表示独一无二的值,用来定义独一无二的对象属性名;
  2. const/let 都是用来声明变量,不可重复声明,具有块级作用域。存在暂时性死区,也就是不存在变量提升。(const一般用于声明常量);
  3. 变量的解构赋值(包含数组、对象、字符串、数字及布尔值,函数参数),剩余运算符(...rest);
  4. 模板字符串(${data});
  5. 扩展运算符(数组、对象);;
  6. 箭头函数;
  7. Set和Map数据结构;
  8. Proxy/Reflect;
  9. Promise;
  10. async函数;
  11. Class;
  12. Module语法(import/export)。

箭头函数和普通函数有什么区别?

1)写法不同

箭头函数比普通函数更简洁:

2)箭头函数没有自己的this

箭头函数不能作为构造函数,也没有自己的this,它只会在自己作用域的上一层继承this。

所以箭头函数中this的指向在它在定义时已经确定了,之后不会改变:

3)普通函数有arguments方法,箭头函数没有

4)箭头函数没有new.target。new.target是用来检测函数是否被当做构造函数使用,他会返回一个指向构造函数的引用:

5)箭头函数没有变量提升

6)箭头函数不能作为构造函数使用

深浅拷贝

拷贝就是浅层次的拷贝 只拷贝一层

如果拷贝对象的属性是数据类型就拷贝它的值

如果是引用类型就拷贝的是内存地址


深拷贝就是递归拷贝深层次

属性为对象时,深拷贝是新开栈 两个对象指向不同的地址


JavaScript中存在两大数据类型:基本类型、引用类型

基本类型数据保存在在栈内存中,引用类型数据保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中。

浅拷贝:指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝

如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址

即浅拷贝是拷贝一层,深层次的引用类型则共享内存地址

在JS中存在浅拷贝的API有:Object.assign()、[].slice()、[].concat()、...运算符

深拷贝:递归拷贝深层次,属性为对象时,深拷贝是新开栈,两个对象指向不同的地址

JS深拷贝:JSON.parse(JSON.stringify(对象));

第三方lodash的deepCone()

同源策略

是一个安全策略,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击

具体表现为浏览器在执行脚本前,会判断脚本是否与打开的网页是同源的,判断协议、域名、端口是否都相同,相同则表示同源。

其中一项不相同就表示跨域访问。会在控制台报一个CORS异常,目的是为了保护本地数据不被JavaScript代码获取回来的数据污染,

因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。

DOM 同源策略: 禁止对不同源页面 DOM 进行操作

同源策略限制的内容有:1.Cookie ,LocalStorage等存储性内容 , 2.DOM节点 3.AJAX 请求发送后,结果被浏览器拦截了

跨域

什么是跨域: 浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域

JSONP

通过客户端的script标签发出的请求方式 向服务器请求JSON数据,这样不受同源政策限制 需要和后端代码对接

优点:

兼容性比较好,可用于解决主流浏览器的跨域数据访问的问题

不受到同源策略的限制,在请求完毕后可以通过调用 callback 的方式回传结果

缺点:

仅支持get请求;

具有局限性,不安全,可能会受到XSS攻击;

只支持跨域 HTTP 请求这种情况,不能解决不同域的两个页面之间如何进行 Javascript 调用的问题

跨域资源共享(CORS):

“跨域资源共享(cors)可以放宽浏览器的同源策略,可以通过浏览器让不同的网站和不同的服务器之间通信。

服务器代理(Proxy) 一般都用这个,因为vue.config中会自动配置

因为服务器和服务器之间是不存在跨域问题的

代理服务器是介于前端和后端之间的中间服务层,前端向代理服务器发送请求时,代理服务器允许跨域请求,

然后代理服务器将前端请求的接口,转发给目标服务器。

原生AJAX

ajax是一种异步通信的方法,从服务端获取数据,达到局部刷新页面的效果。 过程:

  1. 创建XMLHttpRequest对象;
  2. 调用open方法传入三个参数 请求方式(GET/POST)、url、同步异步(true/false);
  3. 监听onreadystatechange事件,当readystate等于4时返回responseText;
  4. 调用send方法传递参数。

常见状态码

blog.csdn.net/w19981225/a…

以下状态码意义自行查询

*200( 成功) 、 *202 已接受),203(非授权信息) ***** 204( 无内容) 、205(重置内容)

300(多种选择)、 ***** 301(永久移动),302(临时移动),303(查看其他位置)*304(未修改)、

305(使用代理),307(临时重定向)

*400(错误请求) 、 ***** 401(未授权) 、 ***** 403(禁止) 、 ***** 404(未找到) 405(方法禁用)408(请求超时)

*500(服务器内部错误) 503(服务不可用) 504(网关超时)505(HTTP 版本不受支持)

输入一个 URL到这个页面呈现出来,中间会发生什么?

DNS 解析 ->TCP 连接 -> 发送 HTTP 请求 ->服务器处理请求并返回 HTTP 报文 -> 浏览器解析渲染页面 -> 连接结束

一、DNS域名解析

输入URL后,首先需要找到这个URL域名的服务器IP,为了寻找这个IP,浏览器首先会寻找缓存,查看缓存中是否有记录,缓存的查找记录为:浏览器缓存->系统缓存->路由器缓存,缓存中没有则查找系统的 hosts 文件中是否有记录,如果没有则查询 DNS 服务器

二、建立TCP连接

根据 IP 地址,客户端与服务端进行三次握手,建立连接。

  • 客户端首先给服务端发送一个带SYN标志的数据包。
  • 服务端收到后,回传一个带有SYN/ACK标志的数据包以表示正确传达,并确认信息。
  • 最后,客户端再回传一个带ACK标志的数据包,代表“握手”结束。

三、传输数据

连接后,客户端向服务端发起 HTTP 请求,服务器接收到请求后,返回请求静态资源,并同时调用服务器请求接口数据。

四、关闭TCP连接

数据传输完成,客户端与服务端进行四次挥手,关闭连接。

  • 第一次挥手:主动关闭方发送一个FIN,用来关闭主动关闭方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方,主动关闭方已经不会再给被动关闭方发送数据了(当然,在FIN包之前发送出去的数据,如果没有收到对应的ACK确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可以接收数据。
  • 第二次挥手:被动关闭方收到FIN包后,给对方发送一个ACK,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。
  • 第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,被动关闭方的数据也发送完了,不会再给主动关闭方发送数据了。
  • 第四次挥手:主动关闭方收到FIN后,给被动关闭方发送一个ACK,确认序号为收到序号+1,至此,完成四次握手。

\

五、渲染页面

对于浏览器根据服务端返回的静态资源,浏览器使用 Native GUI 引擎渲染 HTML 和 CSS ;使用 JS 引擎加载 JS 。

  • 将 HTML 节点解析成 DOM 树结构
  • 将 CSS 解析成 CSSOM 规则树
  • 将 DOM 与 CSSOM 组合成 Render-tree(渲染树)
  • 布局:计算出每个节点在屏幕中的位置
  • 绘制:即遍历render树,并使用UI后端层绘制每个节点

\

六、加载 JavaScript 脚本

虽然 HTML\CSS 与 JS 是通过不同的引擎加载,但是却是互斥的,即加载 HTML\CSS 时,JS 会停止加载,相反亦然,这是因为 JS 引擎可以操作 DOM,改变样式、内容等。所以当执行了 JS 之后,渲染树要重新构建。

\

谈谈localstorage、sessionstorage和cookie的区别

sessionStorage、localStorage和cookie共同点:都是保存在浏览器端、且同源的

区别在于:

1、cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下

2、存储大小限制也不同,cookie数据不能超过4K,同时因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大

3、数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭

4、作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localstorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的


你怎么理解原型和原型链的概念?

_proto

就是将所有的对象共用的属性放在一个共用属性组成的对象里,然 后让每一个对象的 __proto__存储这个「共用属性组成的对象」的地址

这个共用属性其实就是原型,原型出现的目的就是为了减少不必要的内存消耗。。

_prototype

而原型链就是对象通过__proto__向当前实例所属类的原型上查找属性或方法的机制,

如果找到Object的原型上还是没有找到想要的属性或者是方法则查找结束,最终会返回undefined

每一个函数都有一个prototype属性,这个属性指向函数的原型对象。

每一个对象(除null)都会有的属性__proto__,这个属性指向该对象的原型

每个原型都有一个constructor属性,指向该关联的构造函数。

你知道闭包是什么?

声明一个变量,声明一个函数,在函数内部访问外部的变量,那么这个函数加这个变量叫做闭包

用途: 1.从外部读取内部的变量 2.将创建的变量的值始终保持在内存中:

相当于一个函数有权访问另一个函数作用域的变量

闭包就是在一个函数内部创建另一个函数,让你可以在一个内层函数中访问到其外层函数的作用域。

又或者说,闭包就是能够读取其他函数内部变量的函数。

优点:

闭包的优点是可以避免全局变量的污染;

(1)保证函数不受外界干扰,实现封装,避免命名冲突(2)可以在内存中保存函数变量,充当缓存

缺点

内存消耗很大,容易造成内存泄漏, 要谨慎使用

解决方法是,在退出函数之前,将不使用的局部变量全部删除。

作用:

防抖、节流属于性能优化方面的知识,可防止浏览器卡死,

防抖必须等最后一次触发事件后才能执行事件函数,而节流是规定时间内必定会执行一次且只执行一次事件函数。

使用:

定义一个外部函数

定义一个内部函数

内部函数使用了外部函数的变量

外部函数返回了内部函数,这里返回的内部函数就是闭包

谈谈你对HTTP缓存的理解

HTTP缓存分为:强制缓存和协商缓存

http 是明文传输,没有安全保证,对服务端和客户端来说都无法验明双方身份

https 使用了ssl加密方式,服务端和服务端可以验明双方的身份,安全有了一定的保障。但是需要解密和加密,对性能会造成一定的影响。

http端口号是80 ,https端口号是443。

async/await是什么? 呃singke 呃wei特

ES7 标准中新增的 async 函数,从目前的内部实现来说其实就是 Generator 函数的语法糖。

它基于 Promise,并与所有现存的基于Promise 的 API 兼容。

async 关键字

  1. async 关键字用于声明⼀个异步函数(如 async function asyncTask1() {...})
  2. async 会⾃动将常规函数转换成 Promise,返回值也是⼀个 Promise 对象
  3. async 函数内部可以使⽤ await

await 关键字

  1. await 用于等待异步的功能执⾏完毕 var result = await someAsyncCall()
  2. await 放置在 Promise 调⽤之前,会强制async函数中其他代码等待,直到 Promise 完成并返回结果
  3. await 只能与 Promise ⼀起使⽤
  4. await 只能在 async 函数内部使⽤

相较于 Promise,async/await有何优势?

  1. 同步化代码的阅读体验(Promise 虽然摆脱了回调地狱,但 then 链式调⽤的阅读负担还是存在的)
  2. 和同步代码更一致的错误处理方式( async/await 可以⽤成熟的 try/catch 做处理,比 Promise 的错误捕获更简洁直观)
  3. 调试时的阅读性, 也相对更友好

谈谈对于继承的理解

原型继承

原型继承: 通过改造原型链, 利用原型链的语法, 实现继承方法!

组合继承

组合继承有时候也叫伪经典继承,指的是将原型链 和 借用构造函数 call 技术组合到一块

寄生组合继承

VUE

什么是 M V VM

Model-View-ViewModel 模式

Model 层: 数据模型层

通过 Ajax、fetch 等 API 完成客户端和服务端业务模型的同步。

View 层: 视图层

作为视图模板存在,其实View 就是⼀个动态模板。

ViewModel 层: 视图模型层

负责暴露数据给 View 层,并对 View 层中的数据绑定声明、 指令声明、 事件绑定声明, 进行实际的业务逻辑实现。

数据变化了, 视图自动更新 => ViewModel 底层会做好监听Object.defineProperty,当数据变化时,View 层会自动更新

视图变化了, 绑定的数据自动更新 => 会监听双向绑定的表单元素的变化,⼀旦变化,绑定的数据也会得到⾃动更新。\

优点

  1. 实现了视图(View)和模型(Model)的分离,降低代码耦合、提⾼视图或逻辑的复⽤性
  2. 提⾼了可测试性:ViewModel 的存在可以帮助开发者更好地编写测试代码
  3. 能⾃动更新 DOM:利⽤双向绑定,数据更新后视图⾃动更新,让开发者从繁琐的⼿动操作 DOM 中解放出来

缺点

  1. Bug 难被调试:因为使⽤了双向绑定的模式,当我们看到界⾯发生异常了,有可能是 View 的代码产生的 Bug,也有可能是Model 代码的问题。数据绑定使得⼀个位置的 Bug 被快速传递到别的位置,要定位原始出问题的地⽅就变得不那么容易了可采用的调试方案:(1) 注释掉一段代码, 确定代码的位置(2) debugger 打断点 或者 console 进行调试
  2. 在⼀个⼤的模块中 Model 也会很⼤,虽然使⽤上来说⽅便了,但如果⻓期持有不释放内存,就会造成更多的内存消耗 占用的是 浏览器的 内存

\

Vue的组件data为什么必须是一个函数?

new Vue是一个单例模式,不会有任何的合并操作,所以根实例不必校验data一定是一个函数。

组件的data必须是一个函数,是为了防止两个组件的数据产生污染。 如果都是对象的话,指向同一个地址。 而如果是函数返回的对象,会产生两个空间对应的内存地址。

Vue组件生命周期有哪些?

  1. beforeCreate 创建前
  2. created 创建后
  3. beforeMount 在挂载之前被调用,render尚未被调用 挂载前
  4. mounted el 被新创建的vm.$el替换,并挂载到实例上去之后调用 挂载后
  5. beforeUpdate 数据更新时,被调用,发生在虚拟Dom重新渲染和打补丁之前 更新前
  6. update 由于数据更改导致的虚拟Dom重新渲染和打补丁,在这之后调用 更新后
  7. beforeDestroy 实例销毁之前调用 销毁前
  8. destroyed 实例销毁之后调用,调用后Vue实例的所有东西都会被解绑,所有的事件监听会被移除,子实例被 销毁,该钩子在服务端渲染期间不被调用 销毁后
  9. keep-alive(activated & deactivated) 渲染后通过

父子组件生命周期顺序?

子组件的生命周期嵌套在父组件的beforeMount和mounted之间

如何监听子组件的生命周期?

在子组件里通过vm.$emit()触发一个自定义事件,在父组件中监听该事件执行对应函数

使用@hook:生命周期函数名称=“回调函数”

在Vue中网络请求应该放在哪个生命周期中发起?

至少在 created 之后, 因为数据才基本初始化完毕, 当然 mounted 中也可以 (比created稍晚一些)

v-show和v-if的区别是什么?

共同点:v-if 和 v-show 都能实现元素的显示隐藏
区别:
1. v-show 只是简单的控制元素的 display 属性,而 v-if 才是条件渲染(条件为真,元素将会被渲染,条件为假,元素会被销毁);
2.  v-show 有更高的首次渲染开销,而 v-if 的首次渲染开销要小的多;
3. v-if 有更高的切换开销,v-show 切换开销小;
4. v-if 有配套的 v-else-if 和 v-else,而 v-show 没有
5. v-if 可以搭配 template 使用,而 v-show 不行

v-for和v-if哪个优先级更高?

v-for和v-if 不能在同一个标签中使用。先处理v-for,再处理v-if。

如果同时遇到的时候,应该考虑先用计算属性处理数据,在进行v-for,可以减少循环次数。

v-for和v-if为何不推荐同时使用?

v-for的优先级高于v-if,所以不管条件是否成立,v-for都会做循环,所以是达不到先判断再循环的作用。

如果存在需要先判断条件是否成立,再循环数据的场景我们可以使用template标签使用v-if指令做条件判断,在tempalte中的子标签做循环。

<template v-if="condition">
  <div v-for="(item, index) in itemList"></div>
</template>

组件的传值方式有哪些?

  1. props和emit:父组件向子组件传递数据,通过prop传递。子组件传递数据给父组件是通过emit
  2. parent、children获取当前组件的父组件和当前组件的子组件
  3. attrs和listeners 。
  4. 父组件通过provide提供,子组件通过inject注入变量 祖孙间通信 层级嵌套比较多
  5. ref获取实例通过ref获取实例 通过ref获取组件实例 获取它的值
  6. eventBus 平级组件数据传递 this.eventBus.eventBus.emit('eventName', param1,param2,)触发事件

this.eventBus.eventBus.on('eventName', (param1,param2,...)=>{}) 监听事件

  1. Vuex export default new Vuex.Store({

state: {password:93,

})

组件模板中

{{$store.state.password}}

组件JS中

this.$store.state.password

为什么scoped能阻止组件间相互污染 相互影响

如果一个项目的所有style标签都加上了scoped属性,相当于实现了样式的模块化。

Vue中的scoped属性的效果主要是通过PostCss实现的。

PostCSS给一个组件中的所有dom添加了一个独一无二的动态属性,

给HTML的dom节点添加一个不重复的data属性(例如: data-v-5558831a)来唯一标识这个dom元素

还有一个scoped穿透 就是想在局部组件中修改第三方组件库的样式

而又不想去除scoped属性造成组件之间的样式覆盖。

就是外面新建一个sass或者less的装css样式的文件夹 然后再引入进来也可以达到一个覆盖的作用

然后就是sass和less的样式穿透 使用/deep/

\

computed和watch的区别是什么?

\

  1. computed和watch都基于watcher来实现的。
  2. computed的属性是具备缓存的,依赖的值不发生变化,对其取值时计算属性方法不会重复执行
  3. watch是监控值的变化,当值发生改变的时候,会调用回调函数

当计算属性所以依赖的值 其中有一个发生变化时才会重新执行

没有发生变化时不会执行的,因为computed的属性是具备缓存的,

依赖的值不发生变化,对其取值时计算属性方法不会重复执行

watch 的方法和属性:handler 方法 immediate 属性 默认执行一次 deep 属性 深度监听对象

开发学习vue过程中有自己编写过vue组件的经验吗?(待完善)

button按钮

主要是根据它props传进来的值 ,对组件的一些样式进行操作

\

\

请说明key的作用和原理?

  • key的作用主要是为了更高效的对比虚拟DOM中每个节点是否是相同节点;
  • Vue在patch过程中判断两个节点是否是相同节点,key是一个必要条件,渲染一组列表时,key往往是唯一标识,所以如果不定义key的话,Vue只能认为比较的两个节点是同一个,哪怕它们实际上不是,这导致了频繁更新元素,使得整个patch过程比较低效,影响性能;
  • Vue判断两个节点是否相同时主要判断两者的key和元素类型等,因此如果不设置key,它的值就是undefined,则可能永 远认为这是两个相同的节点,只能去做更新操作,这造成了大量的dom更新操作,明显是不可取的。

用index赋值key 用什么不好的地方

删掉一个index 就会破坏整个顺序 index不具备唯一标识的那个条件

为何在v-for中使用key?

在diff算法中通过tag和key来判断,是否为sameNode,减少渲染次数,提升渲染的性能

什么是Mixin(混入)

将组件的公共逻辑或者配置提取出来,哪个组件需要用到时,直接将提取的这部分混入到组件内部即可。

这样既可以减少代码冗余度,也可以让后期维护起来更加容易。

Mixin像 Vuex

mixin 一个对象 这个对象里面可以包含Vue组件中的一些常见配置,如data、methods、created等等。

局部混入和全局混入

优点

提高代码复用性

无需传递状态

维护方便,只需要修改一个地方即可

缺点

命名冲突

滥用的话后期很难维护

不好追溯源,排查问题稍显麻烦

不能轻易的重复代码

Vue 响应式原理是怎么实现的?

响应式的核心是通过 Object.defineProperty 拦截对数据的访问和设置

响应式的数据分为两类:

①对象,循环遍历对象的所有属性,为每个属性设置 getter、setter,以达到拦截访问和设置的目的,如果属性值依旧为对象,则递归为属性值上的每个key设置 getter、setter访问数据时(obj.key)进行依赖收集,在dep中存储相关的watcher设置数据时由dep通知相关的watcher去更新

②数组,增强数组的那7个可以更改自身的原型方法,然后拦截对这些方法的操作添加新数据时进行响应式处理,然后由 dep 通知 watcher 去更新,删除数据时,也要由 dep 通知 watcher 去更新。

Vue中如何检测数组的变化?

vue中对数组没有进行defineProperty,而是重写了数组的7个方法。 分别是:push、shift、pop、splice、unshift、sort、reverse

因为这些方法都会改变数组本身,数组里的索引和长度是无法被监控的。

Vue为什么要用虚拟DOM?

  1. 虚拟dom就是用js对象来描述真实Dom,是对真实Dom的抽象
  2. 由于直接操作Dom性能低,但是js层的操作效率高,可以将Dom操作转化成对象操作。最终通过diff算法比对差异进行更新Dom
  3. 虚拟Dom不依赖真实平台环境,可以实现跨平台

【虚拟DOM保证性能下限】

Vue的diff算法原理是什么?

Vue的diff算法是平级比较,不考虑跨级比较的情况。内部采用深度递归的方式+双指针方式比较

  1. 先比较两个节点是不是相同节点
  2. 相同节点比较属性,复用老节点
  3. 先比较儿子节点,考虑老节点和新节点儿子的情况
  4. 优化比较:头头、尾尾、头尾、尾头
  5. 比对查找,进行复用

谈谈Vue的性能优化有哪些?

\

  1. 尽量减少data中的数据,合理的设置响应式数据
  2. 使用数据时,缓存值的结果,不频繁取值
  3. 合理设置key,key保证唯一
  4. v-show(频繁切换性能高)和v-if的合理使用
  5. v-if和v-for不能连用
  6. 采用函数式组件 -> 函数式组件开销低
  7. 采用异步组件 -> 借助webpack的分包策略
  8. 使用keep-alive来缓存组件
  9. 虚拟滚动、时间分片等策略
  10. 数据冻结
  11. 用路由懒加载、异步组件
  12. 防抖、节流
  13. 如果需要使用v-for给每项元素绑定事件时使用事件代理

\

\

如何在vue项目种使用echats?

\

大概就是通过ref获取到你要挂载的哪个区域 然后在mounted里面通过echats一些配置阿 然后把它挂载到你先挂载的区域上去

使用echats大概实现了什么功能?

(1,强大的Echarts提供创新的拖拽重计算

 (2.数据视图、值域漫游等功能特性

 3.大大增强了用户体验

4.赋予了用户对数据进行挖掘、整合的能力

5.方便丰富的可视化图表模板

6。帮助用户高效制作漂亮动态的大数据图表

\

vue3和vue2的区别?

  1. 生命周期的区别 vue3基于vue2的生命周期上, beforeCreate ,created改成了setup其余的除去 beforeDestroy 改为onBeforeUnmount 销毁前 destroyed 改为了 onUnmounted 销毁后 都只是在vue2上的基础上加个on
  2. Vue2 响应式原理基础是 Object.defineProperty;Vue3 响应式原理基础是 Proxy。
  3. Vue3 的cacheHandler可在第一次渲染后缓存我们的事件。相比于 Vue2 无需每次渲染都传递一个新函数。
  4. Vue3 由 TypeScript 重写,相对于 Vue2 有更好的 TypeScript 支持。
  5. vue3有setUp语法糖

ref和reactive区别

ref:const xxx = ref (initValue) 接受的数据类型:基本类型,引用类型 作用:把参数加工成一个响应式对象,全称为reference对象(我们下面一律简称为ref对象) 核心原理:如果使用的是基本类型响应式依赖Object.defineProperty( ),如果ref使用的是引用类型,底层ref会借助reactive的proxy 定义响应式

reactive:const xxx = ref (源对象) 接受的数据类型:引用类型 作用:把参数加工成一个代理对象,全称为proxy对象 核心原理:基于Es6的Proxy实现,通过Reflect反射代理操作源对象,相比于reactive定义的浅层次响应式数据对象,reactive定义的是更深层次的响应式数据对象

watch 与watchEffect的区别 first:watchEffect不需要指定监听的属性,自动收集依赖;watch需要指定监听的属性

second:watchEffect拿不到旧值;watch可以拿到旧值

third:watchEffect在组件第一次就会收集依赖,然后收集到的依赖发生了变化,回调才会再次执行;watch就不是了。一开始就指定了依赖。

vue中v-model和.sync修饰符区别

  • 相同点:都是语法糖,都可以实现父子组件中的数据的双向通信。

v-model针对更多的是最终操作结果,是双向绑定的结果,是value,是一种change操作。

.sync针对更多的是各种各样的状态,是状态的互相传递,是status,是一种update操作。

vue-router 路由模式有几种?

vue-router 有 3 种路由模式:hash、history、abstract

  • ·URL 中 hash值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;

History原理:

history 路由模式的实现主要基于存在下面几个特性:

  • pushState 和 repalceState 两个 API 来操作实现URL 的变化 ;
  • 我们可以使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染);
  • history.pushState() 或 history.replaceState() 不会触发 popstate事件,这时我们需要手动触发页面跳转(渲染)

abstract : 支持所有JavaScript运行环境,如Node.js服务器端。如果发现没有浏览器的API`,路由会自动强制进入这个模式.

Vue双向绑定原理?

7.1 基本认知

在 Vue 2.x 中,利⽤的是 Object.defineProperty 去劫持对象的访问器(Getter、Setter),

当对象属性值发⽣变化时可获取变化,然后根据变化来作后续响应;(一个一个的劫持)

在 Vue 3.0 中,则是通过 Proxy 代理对象进⾏类似的操作。劫持的是整个对象, 只要对象中的属性变化了, 都能劫持到

7.2 Object.defineProperty和Proxy的优缺点?

Proxy

  • 可以直接监听整个对象,⽽⾮是对象的某个属性
  • 可以直接监听数组的变化
  • 拦截⽅法丰富:多达13种,不限于getsetdeleteProperty、has 等。比 Object.defineProperty 强大很多

Object.defineProperty

  • 兼容性较好(可⽀持到 IE9)

\

如何理解Vue的响应式系统?

(考察MVVM) M: model数据模型, V:view视图模型, VM: viewModel视图数据模型

双向:

  1. 视图变化了, 数据自动更新 => 监听原生的事件即可, 输入框变了, 监听输入框input事件
  2. 数据变化了, 视图要自动更新 => vue2 和 vue3
  3. Vue3 响应式的 核心Proxy

CSS

如何理解css盒子模型?

CSS 盒子模型本质上是一个盒子。封装了周围的 HTML 元素。

它包括:外边距(margin)、边框(border)、内边距(padding)、实际内容(element)四个属性。

content-box:标准盒模型,又叫做 W3C盒模型,一般在现代浏览器中使用的都是这个盒模型

border-box:怪异盒模型,低版本IE浏览器中的盒模型

box-sizing:content-box; padding 和 border 不被包含在定义的 width 和 height 之内。

盒子的实际宽度=设置的width+padding+border

box-sizing:border-box; padding 和 border 被包含在定义的 width 和 height 之内。

盒子的实际宽度=设置的 width(padding和border 不会影响实际宽度)

设置了border-box的属性值后,表现的宽度 = width + padding + border-width

\

BFC(块级格式化上下文)

BFC 是一个独立的布局环境。可以理解为一个区域,在这个区域内的元素无论如何布局排版,都不影响区域外的元素

原理:

1内部的 盒子会在垂直方向,从顶部开始一个接着一个地放置;

2盒子垂直方向的距离由 margin (外边距)决定,属于同一个 BFC 两个相邻 盒子 的 margin 会发生重叠;

3.计算 BFC 的高度时,浮动元素也参与计算

触发 BFC 条件(即脱离文档流)

0)、根元素,即 HTML 元素(最大的一个 BFC )

行内块( display 为 inline-block )

表格单元( display 为 table、table-cell、table-caption、inline-block 等 HTML 表格相关的属性 )

弹性盒( display为 flex 或 inline-flex )

默认值。内容不会被修剪,会呈现在元素框之外(overflow 不为 visible)

\

使用场景:

自适应两(三)栏布局(避免多列布局由于宽度计算四舍五入而自动换行)

避免元素被浮动元素覆盖

以让父元素的高度包含子浮动元素,清除内部浮动

除边距重叠现象,分属于不同的 BFC 时,可以阻止 margin 重叠

\

\

position取值

\

static:默认值

relative:相对定位 不脱离文档流 保留原来位置进行定位,相对于自己原来的位置进行定位

absolute:绝对定位 脱离文档流 脱离原来位置进行定位。

fixed:固定定位 脱离文档流 相对于屏幕视口进行定位。

Webpack

在webpack中 一般只能打包js的代码 为了打包样式代码 它用了一些loder 主要用了哪些 ?

1、file-loader:把⽂件输出到⼀个⽂件夹中,在代码中通过相对 URL 去引⽤输出的⽂件。

2、url-loader:和 file-loader 类似,但是能在⽂件很⼩的情况下以 base64 的⽅式把⽂件内容注⼊到代码中去。

3、source-map-loader:加载额外的 Source Map ⽂件,以⽅便断点调试。

4、image-loader:载并且压缩图⽚⽂件。

5、babel-loader:将ES6转化为ES5。

6、css-loader:加载 CSS,⽀持模块化、压缩、⽂件导⼊等特性。

7、style-loader:把 CSS 代码注⼊到 JavaScript 中,通过 DOM 操作去加载 CSS。

8、eslint-loader:通过 ESLint 检查 JavaScript 代码。

webpack默认配置及需要用到的配置

1.entry:指定webpack打包入口文件

2-output:打包转换后的文件输出到磁盘位置

3-mode 用来指定当前的构建环境

4-loader 模块解析,模块转换器,用于把模块原内容按照需求转换成新内容。

5-moudle 模块,对指定的文件类型进行指定的loader解析

6.Plugins:[],webpack的扩展补充插件

7.devtool:” ” 用作调试 在找错时有帮助 ,开发工具

8.resolve:{}解析模块路径/精确路径

9.devserver:{},为静态文件提供服务,自动刷新和热替换

项目过程中遇到的实际问题解决