vue面试题汇总 1

简介: vue面试题汇总

1. 谈谈你对MVVM开发模式的理解?

MVVM是一种简化用户界面的实践驱动编程方式。在当前主流的前后端分离的开发模式中,MVVM模式的优越性日益体现,相较于经典的MVC模式,其对于程序模块的封装很好地解决了前后端信息交互的冗余和繁琐


MVVM分为Model、View、ViewModel三者。

Model 代表数据模型,数据和业务逻辑都在Model层中定义;

View 代表UI视图,负责数据的展示;

ViewModel 负责监听 Model 中数据的改变并且控制视图的更新,处理用户交互操作;

Model 和 View 并无直接关联,而是通过 ViewModel 来进行联系的,Model 和 ViewModel 之间有着双向数据绑定的联系。因此当 Model 中的数据改变时会触发 View 层的刷新,View 中由于用户交互操作而改变的数据也会在 Model 中同步。

这种模式实现了 Model 和 View 的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作 dom。


为什么使用MVVM:低耦合,可复用,独立开发,可测试


2. v-if 和 v-show 有什么区别?

手段

v-if是动态的向DOM树内添加或者删除DOM元素;

v-show是通过设置DOM元素的display样式属性控制显隐;

编译

v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译;

v-show是在任何条件下,无论首次条件是否为真,都被编译,然后被缓存,而且DOM元素保留;

性能消耗:

v-if有更高的切换消耗;

v-show有更高的初始渲染消耗

3.r o u t e 和 route和route和router区别

$route 是“路由信息对象”,包括 path,params,hash,query,fullPath,matched,name 等路由信息参数

$router 是“路由实例”想要导航到不同URL 对象包括了路由的跳转方法,钩子函数等。通过push、replace、go、back等方法,来实现页面间的跳转

4.vue自定义指令

vue指令


vue2


局部注册:directive选项

directives: {
 'focus': {
   bind(el, binding, vnode) {
     el.focus()
   }
 }
}

全局注册:main.js

Vue.directives('focus',{
  bind(el, binding, vnode) {
     el.focus()
   }
})

生命周期:


bind:只调用一次,指令第一次绑到元素调用,用于初始化

inserted:被绑定元素插入父节点时调用

update:所在组件vnode更新调用

componentUpdate:指令在组件的vnode及子组件的vnode全部更新完调用

ubind:只调用一侧,指令解绑

vue3


局部注册:引入 import { Directive , DirectiveBinding } from ‘vue’ 分别校验vFocus,binding

<template>
<input type="text" v-focus="{ color: 'red' }" />
</template>
<script setup>
const vFocus = {
created(el, binding) {
 el.style.backgroundColor = binding.value.color;
 console.log(el, binding.value.color); //<input type="text" style="background-color: red;"> 'red'
},
};
</script>

全局注册:main.js,app.vue如上引入

import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.directive('focus', {
 created(el, binding) {
     el.style.backgroundColor = binding.value.color;
     console.log(el, binding.value.color); //<input type="text" style="background-color: red;"> 'red'
 }
})
app.mount('#app')

生命周期:


created 元素初始化的时候

beforeMount 指令绑定到元素后调用 只调用一次

mounted 元素插入父级dom调用

beforeUpdate 元素被更新之前调用

update 这个周期方法被移除 改用updated

beforeUnmount 在元素被移除前调用

unmounted 指令被移除后调用 只调用一次

5.vue项目优化

代码层面

长列表性能优化

事件销毁, beforeDestroy生命周期函数内执行销毁逻辑。

图片懒加载

路由懒加载

按需加载插件

v-if,v-for避免同时使用

v-if,v-show选择

keep-alive组件缓存

input防抖节流

基础的web技术优化

开启gzip压缩

浏览器缓存

CDN加速

webpack优化

6.vue模板如何编译

Vue的模板编译就是将“HTML”模板编译成render函数的过程。这个过程大致可以分成三个阶段:


解析阶段:将“HTML”模板解析成AST语法树;

核心 parseHTML( template ,{}) Vue定义了很多匹配HTML的正则表达式 ,parseHTML根据正则匹配

parseHTML是解析模板字符串的“主线程”,它的第一个参数是要解析的模板字符串, 也就是单文件组件中最外层 所包裹的部分;第二个参数是一个选项对象,它会包含一些回调,以及一些配置项。

选项对象:

start( tag, attrs, unary ) 匹配到开始标签时的回调,tag为当前标签的标签名,attrs为该标签上的属性列表,unary为当前标签是否为自闭合标签

end() 匹配到结束标签时的回调

chars(text) 匹配到文本节点的回调

comment(text) 匹配到注释节点的回调,其处理逻辑跟文本的处理逻辑类似

优化阶段:从AST语法树中找出静态子树并进行标记(被标记的静态子树在虚拟dom比对时会被忽略,从而提高虚拟dom比对的性能);

上面简单介绍过,优化阶段的工作就是标记静态子树,标记静态子树后主要有以下两个优点:

生成虚拟dom的过程中,如果发现一个节点是静态子树,除了首次渲染外不会生成新的子节点树,而是拷贝已存在的静态子树;

比对虚拟dom的过程中,如果发现当前节点是静态子树,则直接跳过,不需要进行比对。

标记静态子树的过程分为两个步骤:

遍历AST语法树,找出所有的静态节点并打上标记(注:当前节点及其所有子节点都是静态节点,当前节点才会被打上静态节点的标记)

遍历经过上面步骤后的树,找出静态根节点,并打上标记(注:静态根节点是指本身及所有子节点都是静态节点,但是父节点为动态节点的节点,找到了静态根节点也就找到了“静态子树”)

代码生成阶段:通过AST生成代码字符串,并最终生成render函数。

7.vue2响应式原理

vue 采用了几个核心部件 : Observer ,Dep, Watcher ,Scheduler


observer把一个普通的对象转换成响应式的对象

observer 把对象的每个属性通过 object.defineProperty 转换为带有 getter 和 setter 的属性

Dep 表示依赖, vue 会为响应式对象中的每一个属性,对象本身,数组本身创建一个 dep 实例,每个 dep 实例都可以做两件事情 :

记录依赖:是谁在用我

派发更新:我变了,我要通知那些用我的人

watcher 在函数执行的过程中,如果发生了依赖记录,那么 dep 就会把这个全局变量记录下来,表示有一个 wathcer 用到了我这个属性。

Scheduler 不会立即执行更新,通过nexttick异步更新

8.vue3响应式原理

通过Proxy(代理): 拦截对象中任意属性的变化,包括:属性值的读写,属性的增加,属性的删除等。


通过Reffect(反射): 对源对象的属性进行操作, Reflect不是一个函数对象,因此它是不可构造的。


9.刷新浏览器后,Vuex的数据是否存在?如何解决?

不存在


原因: 因为 store 里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被重新赋值初始化。


我们有两种方法解决该问题:


使用 vuex-along

使用 localStorage 或者 sessionStroage

10.vue和react共同点?区别

共同点:


数据驱动视图

组件化

都使用 Virtual DOM

不同点:


核心思想不同

vue定位就是尽可能的降低前端开发的门槛,让更多的人能够更快地上手开发。这就有了vue的主要特点:灵活易用的渐进式框架,进行数据拦截/代理,它对侦测数据的变化更敏感、更精确。

react 定位就是提出 UI 开发的新思路 React推崇函数式编程(纯组件),数据不可变以及单向数据流,当然需要双向的地方也可以手动实现, 比如借助onChange和setState来实现。

组件写法

React推荐的做法是JSX + inline style, 也就是把 HTML 和 CSS 全都写进 JavaScript 中

Vue 推荐的做法是 template 的单文件组件格式(简单易懂,从传统前端转过来易于理解),即 html,css,JS 写在同一个文件(vue也支持JSX写法)

diff算法

响应式原理

vue2采用object.defineProperty ,vue3采用proxy,reflect

React基于状态机,手动优化,数据不可变,需要setState驱动新的state替换老的state。

11.vue双向数据绑定原理

简易实现:v-model分为两部分,通过v-bind绑定值,再通过v-on:input来通步修改值


原理:


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

通过dep来理清依赖关系,watcher在依赖中添加自身

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

待属性变动dep.notice()通知时,能调动watcher自身的update方法,并处罚compile回调渲染视图

12.computed和watch区别

computed计算属性,watch监听属性


计算属性不在 data 中,它是基于data 或 props 中的数据通过计算得到的一个新值。watch 可以监听的数据来源:data,props,computed内的数据

component中有get和set方法,会默认缓存计算结果。watch不支持缓存,支持异步, immediate监听属性立即执行一次,deep开启深度监听

13.Vuex

Vuex是一种状态管理模式,存在的目的是共享可复用的组件状态。


主要包括以下几个模块:


State => 基本数据,定义了应用状态的数据结构,可以在这里设置默认的初始状态。

Getter => 从基本数据派生的数据,允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。

Mutation => 是唯一更改 store 中状态的方法,且必须是同步函数。

Action => 像一个装饰器,包裹mutations,使之可以异步。用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。

Module => 模块化Vuex,允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。

14.vuex辅助函数

mapState, mapMutations, mapActions, mapGetters


mapState和mapGetters:


两者都放在 computed中,以mapState举例

import { mapState } from 'vuex'

import { mapState } from 'vuex'
computed中
computed:{
  ...mapState(['data'])  //data是vuex存放的state中的属性,此时{{data}}可使用
}

mapMutations, mapActions:


放在组件的methods属性中 。使用与上类似

15.vuex模块化使用

当我们开发的项目比较大时,store中的数据就可能比较多,这时我们store中的数据就可能变得臃肿,为了解决这一问题,我们就需要将store模块化(module)


前提:创建两份js文件,含有属性与vuex写法相同,需要通过 namespaced:true开启命名空间store/index.js:在modules中引入文件


使用:


访问state数据:

第一种方式:this.$store.state.moduleA.sum

第二种方式: ...mapState('moduleA',['sum','number'])

action提交mutation

第一种方式:需要传参this.$store.dispatch('moduleB/addZhang',{name:'小明',age:18}) ,无需传参this.$store.dispatch('moduleB/addServer')

第二种方式:...mapActions('moduleB',['addZhang'])

getters计算属性

第一种方式: this.$store.getters['moduleB/firstName']

第二种方式:...mapGetters('moduleB',['firstName'])

16.vue中mixin

mixin(混入): 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。


本质其实就是一个js对象,它可以包含我们组件中任意功能选项,如data、components、methods 、created、computed等等


我们只要将共用的功能以对象的方式传入 mixins选项中,当组件使用 mixins对象时所有mixins对象的选项都将被混入该组件本身的选项中来


具体使用:


创建mixins.js文件

let mixin = {
    created() {
        console.log('我是mixin中的');
    },
    methods: {
        hellow() {
            console.log('你好');
        },
    },
}
export default mixin

局部使用

import mixin from "./mixins";
export default {
  mixins: [mixin],
  mounted() {
    this.hellow();//你好
  },
};

全局使用main.js

import { createApp } from 'vue'
import App from './App.vue'
import mixins from "./mixins";
const app = createApp(App)
app.mixin(mixins)
app.mount('#app')
目录
相关文章
|
2天前
|
JavaScript 前端开发 API
vue面试题目汇总
vue面试题目汇总
40 4
|
2天前
|
缓存 JavaScript 前端开发
Vue常见面试题 标准答案汇总一
Vue常见面试题 标准答案汇总一
67 1
|
2天前
|
监控 JavaScript 前端开发
vue基础面试题10问
vue基础面试题10问
40 0
|
2天前
|
人工智能 缓存 JavaScript
【利用AI刷面试题】AI:十道Vue面试题巩固一下知识
【利用AI刷面试题】AI:十道Vue面试题巩固一下知识
|
2天前
|
存储 JavaScript 安全
Vue基础面试题题目一
Vue基础面试题题目一
31 0
|
2天前
|
JavaScript 数据安全/隐私保护 开发者
常见的vue面试中的proxy和object.defineProperty的区别
常见的vue面试中的proxy和object.defineProperty的区别
|
2天前
|
存储 JavaScript
面试题:扩展运算符(...)的优缺点(vue)
面试题:扩展运算符(...)的优缺点(vue)
43 0
|
2天前
|
缓存 JavaScript 前端开发
vue核心面试题汇总【查缺补漏】(二)
vue核心面试题汇总【查缺补漏】(二)
|
2天前
|
缓存 移动开发 JavaScript
vue核心面试题汇总【查缺补漏】(一)
vue核心面试题汇总【查缺补漏】(一)
108 0
|
2天前
|
JavaScript 前端开发 算法
中秋国庆 前端常见vue面试题(必备)
中秋国庆 前端常见vue面试题(必备)
122 0