准备面试---vue

145 阅读6分钟

谈谈对VUE的理解

vue是一个数据双向绑定的渐进式框架,有很多自己的插件,同样也是一个声明式的UI框架,借助了MVVM的思想,是单页面形式的,可以把一个页面分割为多个组件,从而提高复用性。

什么是MVVM?

首先MVVM是一种设计思想,每个字母代表的是:Modle(数据和业务逻辑层)、View(视图层)、ViewModle(数据渲染视图),View和Modle之间并没有联系,通过ViewModel进行关联,Model和ViewModel之间有着双向数据绑定的联系,用户因为交互在View中改变了数据也会在Modle中直接同步,相反因为数据发生了改变也会在View层直接更新,这种模式实现了Modle和View的数据自动更新,因此开发者只需要关心业务逻辑和数据就可以了,不用自己操作DOM。

什么是MVC?

MVC也是一种设计思想,当数据发生改变的时候会通知视图层去更新,视图层因为用户交互发生数据改变会有Controllor调用Modle层从而改变数据,然后Modle层再通知视图层去更新。

什么是MVP?

MVP和MVC一样的思想,区别就是Controllor和Presenter,MVC是Controllor只控制Modle,没有控制View,MVP是presenter可以控制Modle和View,从而实现View和Modle的同步更新。

Vue的双向绑定是什么原理?以及Vue3的

vue2:
Vue2是使用数据劫持结合发布-订阅模式的方式实现的,当一个vue实例被创建时,vue会遍历data中的属性,并使用Object.difineProperty()方法转换为getter和setter,从而实现数据劫持。当数据发生变化的时候,setter会通知依赖该数据的所有组件进行更新。
vue3:
Vue3中也是使用数据劫持和发布-订阅模式实现的,不同的是Vue3中使用的Proxy对象替代了Object.defineProperty()方法,proxy对象可以拦截并重载对象上的各种操作,包括属性访问、属性赋值、函数调用等。

Proxy和Object.defineProperty()的区别?及优劣

  • Proxy可以拦截对象的所有操作。包括属性访问、属性赋值、函数访问,而Object.defineProperty()只能拦截属性的访问和删除。
  • Proxy可以监听整个对象而不需要监听对象的每个属性,更加高效,而Object.defineProperty()需要给对象的每个属性分开设置getter和setter,增加了代码的复杂度和运行时的开销。
  • Proxy可以动态增加或者删除属性,而Object.defineProperty()不能。
  • proxy可以监听数组的变化,而Object.defineProperty()不能。
  • Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改。

Vue的生命周期有哪些?及Vue3的

vue2

  • beforeCreate(创建前):此时vue的实例还没有被创建,此时data的响应式追踪、event/watcher都还没有被设置,也就是说不能访问data、methods上的方法和数据。适合在该阶段做一些初始化的操作,比如:配置项的处理,全局时间的绑定。
  • created(创建后):此时vue实例已经创建完成,data、methods等都已配置完成,但是渲染节点还没有挂载到DOM上,无法访问$el属性。适合进行数据初始化和异步请求。
  • beforeMount(挂载前):在挂载开始之前被调用,此时已经生成了HTML,但还没挂载到页面上去。适合设置数据或者执行某些操作。
  • mounted(挂载后):在挂载之后被调用,此时实例已经挂载到页面当中,DOM节点已经可见,可以进行DOM操作。适合调用第三方库或者进行DOM操作。
  • beforeUpdate(更新前):数据更新前被调用,发生在重新渲染虚拟DOM和打补丁之前,但是对应的真实DOM还没有被修改。适合在更新之前访问已有DOM,比如手动移除已添加的事件监听器
  • updated(更新后):数据更改导致虚拟DOM重新渲染和打补丁之后调用,组成新的DOM已经更新到页面当中,在这个阶段要避免修改数据,以免导致更新无限循环。
  • beforeDestory(销毁前):此时vue实例还没有被销毁,this也可以正常使用,常用于清除定时器、解绑事件等。
  • destoryed(销毁后):实例被销毁后调用,所有绑定的数据和事件监听都被解绑,所有子实例也都被销毁。

vue3

  • Option Api:中就是把beforeDestory、destoryed改为了beforeUnmount、unmounted。
  • Composition Api :中把beforeCreate、created改为setup函数,beforeDestory、destoryed改为OnBeforeUnmount、OnUnmounted,其余的加On。

Vue组件通信的方式有哪些?

  • 父传子:父组件给子组件身上绑定属性,子组件通过prop来接收。
  • 子传父:父组件通过给子组件监听事件,子组件通过$emit来触发事件,进而传递参数。
  • 依赖注入:父组件使用provide提供数据,子组件通过inject获取数据。
  • eventBus:兄弟组件之间传递参数,$emit传递参数,$on接收。
  • ref/refs:通过ref给组件标记一个唯一的引用,通过$refs来访问组件的实例。
  • parent/children:层级不深的组件,子组件通过$parent可以获取父组件的数据,父组件可以通过$childern来获取子组件身上的数据。
  • attrs/listeners$attrs可以让父组件向子组件传递所有的属性,$listeners可以让子组件向父组件传递所有的事件。
  • 状态管理:vuex或者pinia。

讲一下Vuex和Pinia

这个两个都是官方推出的状态管理库,允许跨组件或页面共享状态,在使用上区别不大。
vuex中有state、Getter、Mutation、Action、Modle,pinia中把Mutation和Action合并成Action。

  • state:存放数据的状态
  • Getter:相当于计算属性一样
  • Mutation:同步函数,更改数据状态的地方
  • Action:异步操作,请求数据,不能直接修改数据状态
  • Modle:切割模块

Vuex的使用流程:页面通过dispath来触发action中的方法,action通过commit来提交到mutation中,mutation会修改state中的值,页面重新渲染。

Vue的指令有哪些?

  • v-if:根据表达式来判断是否渲染,结果为true时渲染,false时不渲染。
  • v-show:根据表达式来判断是否显示隐藏,与v-if的区别在于v-if是是否渲染,v-show是控制dispaly的bolck和none。
  • v-for:遍历数组或对象,循环渲染。
  • v-bind:动态绑定组件的属性
  • v-on:绑定事件监听器
  • v-model:双向数据绑定
  • v-text:更新元素的文本内容
  • v-html:更新元素的html内容
  • v-once:只渲染一次

Vue怎么自定义指令?

  1. 全局:Vue.directive("focus"{})
  2. 局部:directive()
  3. 钩子函数:
Vue.directive('directiveName', {
  // 指令的生命周期钩子
  bind(el, binding, vnode) {
    // 指令绑定时调用
  },
  inserted(el, binding, vnode) {
    // 被绑定元素插入父节点时调用
  },
  update(el, binding, vnode, oldVnode) {
    // 组件更新时调用,可能发生在子组件的更新之前
  },
  componentUpdated(el, binding, vnode, oldVnode) {
    // 组件更新后调用
  },
  unbind(el, binding, vnode) {
    // 指令解绑时调用
  },
});

  1. 钩子函数参数:
  • el:指令所绑定的元素,可以用来直接操作DOM。
  • binding:一个对象,包含指令的信息,如value、name等。
  • vnode:Vue编译生成的虚拟节点。
  • oldVnode:上一个虚拟节点,仅在update和componentUpdated钩子中可用。

Vue的事件修饰符有哪些?

  • .once:只触发一次
  • .self:只触发自己
  • .stop:阻止事件冒泡
  • .prevent:阻止事件默认行为
  • .captrue:使事件捕获,从外到内

computed和watch的区别?

  • 语义上:computed是计算属性,watch是侦听器。
  • 功能上:computed有缓存,只有依赖的数据发生变化时才会重新计算,watch没有缓存,可以监听到每个数据发生变化,并在数据变化时执行回调。computed用于处理对数据的计算或逻辑处理,返回一个新的响应式数据,watch用于观察数据的变化,并执行对应的操作,不会返回新数据。computed是声明式写法,watch是命令式写法,需要手动指出需要监听的数据和执行的回调函数。

data为什么是一个函数不是一个对象?

防止数据污染,对象是引用型数据,当多个实例指向同一个对象的时候,只要一个实例对这个对象进行操作,也会改变其他实例的对象。通过data定义为函数时,数据是以函数返回值的形式定义的,都会调用函数返回一个新的数据对象,修改组件自身的data不会影响到其他组件。

Vue模版编译的原理是什么?

  1. 解析阶段(parse):使用大量的正则表达式对 tempalte 字符串进行解析,将标签、指令、属性等转化为抽象语法树(AST)
  2. 优化阶段(optimize):遍历抽象语法树(AST),找出其中的静态节点并标记,方便diff比较的时候跳过这些节点,提高性能。
  3. 生成阶段(generate):将最终的 AST 转化为 render 函数字符串。

v-model有什么修饰符?

  • .nomber:输入的内容自动转化为数字。
  • .trim:去除首位空格
  • .lazy:change事件的时候再调用

Vue路由的方式有哪些?有什么区别?

  • hash:hash模式不会包含在http请求当中,并且hash不会重新加载页面,在url中对有一个#号。原理是onhashchange()事件。
  • history:使用history不会有#号,初次访问或者刷行都会向服务器发送请求,需要后端配合。原理是H5新增的两个方法:pushState和replaceState来完成的。

$route$router的区别?

  • $route:指的是路由信息对象,包括path、params、name、query等。
  • $router:指的是路由实例,包含了路由的跳转方法和钩子函数。

路由的跳转方法有哪些?

push、go、router-link标签的to方法、replace

路由的钩子函数有哪些?

  • beforeEach:在路由切换之前调用,可以用于进行全局的权限验证或拦截导航。
  • beforeResolve:在路由解析之前调用,可以用于确保异步组件加载完成。
  • afterEach:在路由切换成功后调用,可以用于进行页面埋点等收尾工作。
  • beforeRouteEnter:在路由进入组件之前调用,允许访问组件实例,但无法访问组件的this。
  • beforeRouteUpdate:在路由更新但是仍然复用组件时调用,允许访问组件实例。
  • beforeRouteLeave:在路由离开组件之前调用,允许访问组件实例,可以用于弹出确认对话框等操作。

虚拟DOM是什么?

虚拟Dom是一种前端优化性能的一项技术。通过以javascript对象的形式表示真实Dom树,减少对真实Dom的操作,从而提高页面渲染效率。

虚拟Dom的工作原理是什么?

  • 初始化阶段:当页面加载或组件初始化时,会通过解析模版或渲染函数来创建一个虚拟Dom树。
  • 数据变化:当数据发生变化时,触发视图更新。
  • 更新阶段:在更新阶段,新的数据会与之前的虚拟Dom树进行比较,从而找到需要更新的部分。
  • 应用差异:将比较得到的数据,只更新差异的数据到真实的Dom中。
  • 渲染阶段:将真实的Dom更新到页面当中。

虚拟Dom 的优势在于什么?

  • 减少Dom操作:通过比较新旧虚拟Dom树,只更新变化的部分,避免重复的Dom操作,提高页面渲染的性能。
  • 跨平台:虚拟Dom是javascript对象,不依赖浏览器。
  • 简化开发:开发者无需操作Dom,只需要操作数据,框架会自动处理Dom更新。

diff算法是什么?

diff算法是一种用于比较两树结构的算法。它通过比较新旧虚拟Dom树,找出差异,然后只需要更新差异部分到真实Dom中,从而提高页面渲染性能。

vue项目中的性能优化

1.不要在模板里面写过多表达式

2.循环调用子组件时添加key

3.频繁切换的使用v-show,不频繁切换的使用v-if

4.尽量少用float,可以用flex

5.按需加载,可以用require或者import()按需加载需要的组件

6.路由懒加载