2W字!vue经典面试题,你值得收藏!

1.谈谈你对Vue的理解吧

* 双向绑定
* 虚拟DOM

2.谈谈什么是双向绑定?

* vue是MVVM模式,Model-View-ViewModel , Model 表示数据模型层。 view 表示视图层, ViewModel 是 View 和 Model 层的桥梁,数据绑定到 viewModel 层并自动渲染到页面中,视图变化通知 viewModel 层更新数据。
* 人话,数据层变化,视图层跟着变化。同理,视图层变化,数据层跟着变化。

vue双向绑定流程

1.new Vue()首先执行初始化,对data执行响应话处理,这个过程发生在Observe中。
2.同时对模板进行编译,找到其中动态绑定数据,从data中获取并初始化试图,这个过程发生在Compile中
3.同时定义一个更新函数和Watcher,将来对应数据变化时Watcher会调用更新函数。
4.由于data的某个key在一个视图中可能出现多次,所以每个key都需要一个管家Dep来管理多个Watcher
5.将来data中数据一旦发生变化,会首先找到对应Dep, 通知所有Watcher执行更新函数。

3.谈谈什么是虚拟DOM?

* 虚拟DOM(Virtual DOM)它是一层对真实DOM的抽象,以JavaScript对象(VNode节点)作为基础的树,用对象的属性来描述节点,最终可以通过一系列操作使这棵树映射到真实树上。
* 在javascript对象中,虚拟DOM表现为一个Object对象。并且最少包含标签名(tag)、属性(attrs)、和子元素对象(children)三个属性。
* 虚拟DOM映射到真实DOM要经历VNode的create、diff、path等阶段。
* 创建虚拟DOM就是为了更好将虚拟的节点渲染到页面视图中,所以虚拟DOM对象的节点真实DOM的属性--照应。
* 方便实现跨平台。
* 减少真实DOM操作,提高性能。
* 虚拟DOM包含了增删改查的功能。

4.谈谈vue中,key的原理

* v-for数组中,使用key给每个元素副本添加唯一标识。
* 修改数组中某个元素值时,避免重建整个列表,只需要修改一个DOM元素副本即可。
* 提高修改效率

5.vue2.x中如何监测数组变化?

使用`Object.defineProperty`数据劫持的方式,重写了数组的方法,Vue将`data`中的数组进行了原型链重写,指向了自己定义的数组原型对象。这样当调用数组`api`时,然后通知依赖更新。如果数组中包含着引用类型,会对数组中的引用类型再次递归遍历进行监控。这样就实现了监听数组变化。

6.说说nextTick的使用和原理?

* 在下次DOM更新循环结束之后执行延迟回调。
* vue`在更新`DOM`时是异步执行的。当数据发生变化,Vue将开启一个异步更新队列,试图需要等队列中所有数据变化完成之后,再统一进行更新。

7.vue2.x组件通信方式有哪些?

  • props
  • $emit/$on
  • $children/$parent
  • $attrs/$listeners
  • ref
  • $root
  • eventbus

8.vue2使用的v指令有哪些?

v-show、v-if、v-bind、v-for、v-on、v-html、v-cloak、v-text、v-model、v-pre

9.vue2常用的修饰符有哪些?分别有什么应用场景?

* lazy 光标离开标签,才将值赋值给value
* trim 自动过滤用户输入的首空格字符,而中间的空格不会过滤
* number  自动将用户的输入值转为数值类型
* stop 阻止了事件冒泡,相当于调用了event.stopPropagation方法
* prevent 阻止了事件的默认行为,相当于调用了event.preventDefault方法
* self 只当在event.target是当前元素自身时触发处理函数
* once 事件只执行一次
* capture 用于事件捕获
* keyCode 监听特定键盘按下

10.vue2中v-model原理及自定义组件的使用

v-model可以看成value+input方法的语法糖。原生的v-model,会根据标签的不同生成不同的事件和属性。解析一个指令来。

** 自定义**

父组件写入v-model属性,子组件里面放prop和event

//父组件
<Child v-model="checked"></Child>

//子组件
export default {
  name: 'MyComp',
  props: ['checked'],
  model: {
    prop: 'checked',
    event: 'change'
  }
}

11.vue2中computed和watch区别

computed

* vue会将首次计算属性计算出的结果,缓存起来,反复使用!避免重复计算
* computed用于处理复杂的逻辑运算: 一个数据受一个或者多个数据影响。例如:
* 在computed中的,属性都有一个get和set方法,当数据变化时,调用set方法。

watched

用来处理一个属性改变影响多个数据。用于监控路由、input输入框值的特殊处理等。
监听数据:data、props、computed内的数据
watch支持异步。
监听函数有两个参数,第一个参数是最新的值,第二个参数是输入之前的值,顺序一定是新值,旧值
不支持缓存,监听的数据改变,直接会触发相应的操作。

12.说说你对slot的理解?slot使用场景有哪些?

  slot艺名插槽,花名"占坑",slot在组件模板中占好位置,当使用该组件标签的时候,组件标签里面的内容就会自动填坑(替换组件模板中slot位置),作为承载分发内容的出口。

slot分为以下3种:

  • 默认插槽,父组件在使用的时候,直接在子组件的标签内写入内容即可
  • 具名插槽,子组件用name属性来表示插槽的名字,父组件在使用在默认插槽的基础上加上slot属性,值为子组件插槽name属性值
  • 作用域插槽,子组件在作用域上绑定属性来将子组件的信息传给父组件使用,这些属性会被挂在父组件v-slot接受的对象上。父组件中在使用时通过v-slot:(简写: #) 获取子组件的信息,在内容中使用。

13.vue-router有几种模式,有什么区别?

有两种模式:hash模式和history模式

hash模式
* hash模式是一种把前端路由的路径用井号#拼接在真实URL后面的模式。当井号#后面的路径发生改变时,浏览器并不会重新发起请求,而是会触发hashchange事件
* 优点:浏览器兼容性较好,连IE8都支持。
* 缺点:路径在井号#的后面,比较丑。

history模式

 history API是H5提供的新特性,主要有history.pushState()和history.replaceState(),允许开发者直接更改前端路由,即更改浏览器URL地址不会重新发起请求。
优点:路径比较正规,没有#
缺点:兼容性不如hash, 且需要服务端支持,否则一刷新页面就404了,以最常用的Nginx为例,只需要在配置的location/中增加一行:try_files $uri/index.html

14.Vue项目中如何解决跨域问题?

  • JSONP
  • CORS
  • Proxy
CORS
CORS是一个系统,它由一系列传输的HTTP头组成,这些HTTP头决定浏览器是否阻止前端javascript代码获取跨域请求的响应。
Proxy
Proxy是代理,是一种特殊的网络服务,允许一个(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。一些网关、路由器等网络设备具备网络代理功能。一般认为代理服务有利于保障网络终端的隐私或安全,防止攻击。
方案一:
如果是通过vue-cli脚手架工具搭建项目,我们可以通过webpack为我们起一个本地服务器作为请求的代理对象。
在vue.config.js文件devServer添加proxy属性。
方案二: 
通过配置nginx实现代理

15.怎么定义动态路由?怎么获取传过来的动态参数?

* 很多时候,我们需要将给定匹配模式的路由映射到同一个组件,这种情况就需要定义动态路由。
* 例如,我们可能有一个User组件,它应该对所有用户进行渲染,但用户ID不同。在Vue Router中,我们可以在路径中使用一个动态字段来实现,例如:{path:'/users/id', component: User},其中:id就是路径参数。
* 路径参数用冒号:表示。当一个路由被匹配时,它的params的值将在每个组件中以this.$route.params的形式暴露出来。

16.如果让你从零开始写一个vue路由,说说你的思路。

vue路由原理: 用户点击跳转链接内容切换,页面不刷新

1.定一个creatRouter函数,返回路由实例,实例内部做几件事情
  *  保存用户传入的配置项
  *   监听hash事件或者popstate事件
  *   回调里面根据path匹配对应路由
2.将路由定义成Vue插件,即使用install方法,内部做两件事情:
  *   实现两个全局组件:router-link和router-view,分别实现页面跳转和内容显示
  *   定义两个全局变量: $route和$outer, 组件内可以访问当前路由和路由器实例。

17.vuex有几种属性,它们存在的意义分别是什么?

vuex是一种状态管理模式,存在的目的是共享可复用的组件状态。
有5种属性,分别是State、Getter、Mutation、Action、Module。

State

  • State是Vuex的单一状态树。

Getter

  • 有时候我们需要从store中的state中派生出一些状态,例如对列表进行过滤并计数。
  • Getter类似于Vue的computed对象。是根据业务逻辑来处理State,使得生成业务所需的属性。

Mutations

  • Mutations是唯一用来更改Vuex中状态的方法。
  • Vuex中的mutations非常类似于事件:每个mutations都有一个字符串的事件类型(type)和一个回调函数(handler)。

Action
Action类似于mutation,不同在于:

  • Action提交的是mutation, 而不是直接变更状态。
  • Action可以包含任意操作。

Module

  • 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store对象就有可能变得相当臃肿。为了解决以上问题,Vuex允许我们将store分割成模块(module)。每个模块拥有自己的state、mutation、action、getter、甚至是嵌套子模块---从上至下进行同样方式的分割。
  • Module是将Vuex模块化的对象,目的是更好的维护。

18.vue2与vue3区别

  • 1.vue2使用选项式Api,是将data和methods包括后面的watch,computed等分开管理
  • 2.vue3使用组合式Api,是将相关逻辑放到了一起(类似于原生js开发)。
  • 3.vue3使用了setup语法糖,可以让变量方法不用再写return。
  • 4.vue2data的数据都具有响应式,页面会随着data中的数据变化而变化,vue3中使用ref和reactive函数来使变量成响应是的数据。
  • 5.vue2和vue3的生命周期有差异。
vue2 vue3 描述
beforeCreate setup() 组件实例创建前
created setup() 组件实例创建后
beforeMount onBeforeMount 组件挂载之前
mounted onMounted 组件挂载到实例上去
beforeUpdate onBeforeUpdate 组件数据发生变化,更新之前
updated onUpdated 组件数据更新之后
beforeDestory onBeforeUnmount 组件实例销毁之前
destoryed onUnmounted 组件实例销毁之后
  • 6.vue3除了使用watch, 还引入了副作用监听函数watchEffect,相当于将watch的依赖源和回调函数合并,当任何你有用到的响应式依赖更新时,该回调函数变会重新执行。不同于watch的是watchEffect的回调函数会被立即执行,即({ immediate: true })
  • 7.vue2和vue3组件通信
方式 vue2 vue3
父传子 props props
子传父 $emit emits
父传子 $attrs attrs
子传父 $listeners 无(合并到attrs方式上)
父传子 provide provide
子传父 inject inject
子组件访问父组件 $parent
父组件访问子组件 $ref expose & ref
兄弟传值 EventBus mitt
  • vue3移除了sync的写法,取而代之的是v-model: event的形式。

父组件使用v-model:changePval="msg",子组件发送update:changePval事件进行修改父组件的值。
8.vue2使用Es5是Object.defineProperty对数据劫持,结合发布订阅的方式实现。vue3使用Es6的new Proxy代理, 使用ref或者reactive将数据转化为响应式数据。

19.Vue3.0里为什么要用 Proxy API 替代 defineProperty API ?

Object.defineProperty

  • 只能遍历对象属性进行劫持
  • 检测不到对象属性的添加和删除
  • 数组API方法无法监听到
  • 需要对每个属性进行遍历监听,如果嵌套对象,需要深层监听,造成性能问题。
    Proxy
  • 直接可以劫持到整个对象,并返回一个新对象,我们可以只操作新的对象达到响应式目的。
  • 可以直接监听到数组的变化
  • 不兼容IE。

20.Vue3.0 性能提升主要是通过哪几方面体现的?

编译阶段
  • diff算法优化

vue3在diff算法中想比vue2增加静态标记,其作用是为了发生变化的地方添加一个flag标记,下次发生变化的时候直接找该地方进行比较。

  • 静态提升

vue3中对不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用

  • 事件监听缓存

默认情况下绑定事件行为会被视为动态绑定,所以每次都会去追踪它的变化。开启缓存后,没有了静态标记。也就是说下次diff算法的时候直接使用。

  • SSR优化

当静态内容打到一定量级时候,会用createStaticVNode方法在客户端去生成一个static node, 这些静态node,会被直接innerHtml,就不需要创建对象,然后根据对象渲染。

源码体积
  • 想比vue2,vue3整体体积变小了,除了移出一些不常用的API,在重要的是Tree shanking
  • 任何一个函数,如ref、reactived、computed等,仅仅在用到的时候才打包,没用到的模块都会被摇掉,打包的整体体积变小了。
响应式系统
  • vue2中采用defineProperty来劫持整个对象,然后进行深度遍历所有属性,给每个属性添加getter和setter,实现响应式
  • vue3采用proxy重写了响应式系统,因为proxy可以对整个对象进行监听,所以不需要深度遍历。
posted @ 2022-10-21 19:09  像鱼灵活的猫  阅读(133)  评论(0编辑  收藏  举报