欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

「2022」- 高频前端面试问题汇总--VUE篇

最编程 2024-07-14 09:56:08
...

VUE篇

1.谈谈你对vue的理解:

  • vue 是一套基于第三方的js框架;
  • Vue 是一套用于构建用户界面的渐进式MVVM模式框架;
  • vue 是一套创建单页应用的Web应用框架;

2. 谈谈单页面应用与多页面应用的区别:

单页面(SPA)

  • 概念:只有一个html页面,所有跳转方式都是通过组件切换完成的。
  • 优点:页面之间跳转流畅、组件化开发、组件可复用、开发便捷、易维护。
  • 缺点:首屏加载较慢,当然这个问题现在已经基本被合理化解决了,加载整个项目中使用的css、js,SEO优化不好

多页面(MPA)

  • 概念:整个项目有多个html,所有跳转方式都是页面之间相互跳转的。
  • 优点:首屏加载较快,只加载本页所使用的的css、js,SEO优化较好。
  • 缺点:页面跳转较慢。

3. SPA(单页应用)首屏加载速度慢怎么解决?

  • 减小入口文件积(常用的手段是路由懒加载)
  • 静态资源本地缓存
  • UI框架按需加载
  • 图片资源的压缩
  • 组件重复打包
  • 开启GZip压缩
  • 使用SSR

image.png

4. 谈谈你对MVVM架构模式的理解:

MVVM:它是一个软件架构设计模式,分为三层,Model–View–ViewModel

View层是视图层,也就是用户界面

Model层是指数据模型,对于前端来说就是后端提供的 api 接口

ViewModel层是业务逻辑层也就是交互层,框架封装的核心,它负责将数据与视图关联起来实现双向数据绑定,它的主要职责就是:数据变化后更新视图,视图变化后更新数据

5. 双向数据绑定原理 ?

Vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。主要分为以下几个步骤:

  1. 需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化;

  2. compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图

  3. Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是: ①在自身实例化时往属性订阅器(dep)里面添加自己 ②自身必须有一个update()方法 ③待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。

  4. MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。

image.png

5. 使用 Object.defineProperty() 来进行数据劫持有什么缺点?

在对一些属性进行操作时,使用这种方法无法拦截,比如通过下标方式修改数组数据或者给对象新增属性,这都不能触发组件的重新渲染,因为 Object.defineProperty 不能拦截到这些操作。更精确的来说,对于数组而言,大部分操作都是拦截不到的,只是 Vue 内部通过重写函数的方式解决了这个问题。

在 Vue3.0 中已经不使用这种方式了,而是通过使用 Proxy 对对象进行代理,从而实现数据劫持。使用Proxy 的好处是它可以完美的监听到任何方式的数据改变,唯一的缺点是兼容性的问题,因为 Proxy 是 ES6 的语法。

6. 什么是虚拟DOM ? 优点缺点有哪些?

虚拟DOM的实现大概可以分为三个步骤:

  1. 使用JavaScript对象模拟真实DOM树,对真实DOM进行抽象;

  2. 然后使用diff算法用来比较两棵虚拟DOM树的差异;

  3. 最后通过pach算法将两个虚拟DOM对象的差异应用到真正的DOM树。

优点:它可以保证性能下限,无需手动操作 DOM,还可以进行更方便地跨平台操作

缺点:它在一些要求极高的应用上无法进行极致优化

7. vue的生命周期

组件的生命周期,是vue在创建一个组件的时候针对于不同的阶段提供给开发者自定义使用的一些回调函数,我们俗称钩子函数。

在vue中,一个组件从创建到销毁会经历,数据的初始化,初始化渲染,更新,销毁,以及其他缓存,错误捕获等阶段,每一个阶段都提供回调函数

  • beforeCreate 初始化之前

  • created 初始化后;数据初始化是,数据初始化主要是初始化挂载了,vue中数据选项(data,props,computed,methods,watch等等数据),我们可以利用created生命周期做一些自己的数据初始化工作,比如ajax的初始化请求

  • beforeMount

  • mounted在这个阶段组件已经渲染完毕,我们可以利用这个阶段做一些初始化dom操作,如果有dom操作一定是在这个生命周期,因为这个生命周期才能保证dom已经渲染完成,$el已经可以访问到

  • beforeUpdae

  • updated这个阶段是当有某一个状态发生改变,并且触发视图的重新渲染才会执行,但是在这个生命周期里面我们无法得知是那个属性发生了改变,所以一般情况下不会使用,一般使用$nextTick这个api来代替他

  • beforeDestorey 销毁前

  • destoreyed 销毁后,我们一般需要在销毁的生命周期中,手动去销毁一些自己手动绑定的事件,定时器等,因为vue组件的销毁只会销毁组件自身的一些dom,和数据。但是我们手动绑定的事件定时他并不能知道,所以需要自行销毁

  • 当使用keep-alive组件启用组件缓存后,被缓存的组件会启动两个新的生命周期

  • actived. 组件启用,当组件缓存以后,那么组件初始化相关的生命周期就只会在初始化的时候执行一次,而销毁除了使用$destory()函数手动销毁外,组件不会自动进行销毁,组件的切换逻辑,可以写到actived和deactived中

  • 在vue2.5.0之后添加了errorCaptured这个生命周期,用来捕获一个来自后代组件发生的错误,我也没用过,我只是知道有

8. 在vue单文件组件中,style标签上的scoped属性是干什么的?

style标签上的scoped属性是用来添加样式作用域的,避免组件和组件之间的样式发生冲突,在通过vue-loader编译的时候,会给生成的标签上添加一个data-v-[hashid]的组件标识,在生成的样式中会以属性选择器的方式添加样式,但是使用scoped之后如果我们想通过父组件修改子组件中某个元素的样式,默认不生效,我们可以通过在选择器前面添加 /deep/的方式来突破样式作用域

9. 在vue中组件的data为什么是函数?

因为在vue组件是需要公用的,一个页面同一个组件可能需要重复使用多次,而每一次组件的调用其实就在实例化一个对象,而vue总组件的所有属性都是放在原型上的,也就是多个实例一个原型,如果data中有引用数据类型,那么就会造城,其中一个组件状态发生改变,那么其他组件也会更着发生改变,为了避免这种情况的出现,在组件中吧data改为函数,通过函数去返回一个对象,那么每一次实例化的时候调用函数拿到对象,这样每一个对象都是新的就不存在引用关系了

10. 在vue中watch,computed,methods有什么区别?

定位不一样,功能不一样,

  • 首先watch是用来监听一个数据是否发生改变,如果改变会触发对应的函数,语法是一个对象,里面写不同的监听,写法有两种,第一种函数写法,监听的属性路径作为属性名字,值是一个函数。第二种是对象写法,可以用来监听一整个对象。如果是对象写法有3个属性,handle监听函数,deep是否深度监听,immediate是否首次触发,因为默认情况下watch只有在改变的时候触发,通过设置immediate可以使得watch初始化的时候触发一次

  • 而computed是用来做计算属性的,键值对的写法,属性名就是计算属性的名字,属性值有两种写法,第一种是函数写法,函数不能接受参数,需要有一个返回值,默认情况下computed计算属性会将值进行缓存,如果依赖的状态没有发生改变,使用多次也只处罚一次计算。第二种写法是一个对象,里面有get和set两个函数,get函数在求值时触发,set函数在赋值时触发,也是说第一种写法就是一个只有get方法的计算属。在使用的时候当成属性使用,不要添加括号

  • methods则没有什么特点,键值对的写法,属性名就是函数名称,值就是一个函数,在vue中如果我们有一些请求函数,事件处理函数,一般都会写到methods里面

11. vue中如何创建一个组件?

在vue中创建组件的话我们先要设计组件用例,也就是组件的定位什么(公共组件,容器组件,业务组件,控件),然后起一个语义话的名字,以及思考组件的属性应该有哪些,是否需要提供事件,以及是否需要接受子元素。

在做组件设计的时候如果是公共组件我们应该使用全局组件注册方式,如果是容器组件就相对简单一些路由对应的组件,如果是业务组件一般情况下是不通用的所以会采用局部注册的方式来注册组件,如果是空间则需要适配表单元素的数据双向绑定也就是v-model,需要接受value属性,监听值的改变触发input事件