2023vue面试题
Posted 柒月北辰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2023vue面试题相关的知识,希望对你有一定的参考价值。
1.谈谈你对vue的了解
vue的作者是尤雨溪,2013年受angular启发,开发出比angular更轻的seed框架,2014正式对外发布。
-vue是一套用于构建用户界面的渐进式javascript框架。
-渐进式可以理解为自底层向上逐层的应用,(从简单的应用递进到复杂应用)
-简单应用:只需要一个轻量级小巧的核心库
-复杂应用:可以引入各式各样的vue插件
-vue特点
-采用组件化模式,提高代码复用率、让代码更简洁。
-声明式编码,无需直接操作dom,提高开发效率。
2.数据双向绑定(数据代理)
-通过vm对象来代理data对象中的属性操作(读/写)
-更加方便的操作数据
-原理:通过object.defineProperty()把data对象中的所有属性添加到vm实例上,然后为每一个添加到vm实例上的属性,都指定一个getter和setter,在getter/getter内部去操作(读/写)data中对应的属性。
3.对mvvm的理解
是model-view-viewmodel的缩写,是一种结构模式(设计思想)
model是数据模型,用于对数据的定义和修改等操作。
view是ui视图层,用于渲染页面。
viewModel:负责监听model中数据的改变并控制属兔更新,处理用户交互操作。
修改View层,Model对应数据发生变化
Model数据变化,不需要查找DOM,直接更新View
4.修饰符
事件修饰符(可以连续使用)
-.prevent阻止默认行为
-.stop阻止冒泡
-.once事件触发一次
-.capture使用事件的捕获模式
-.self只有event.target是当前操作的元素才会触发事件
-.passive事件默认行为立即执行,无需等待事件回调执行完毕。
键盘修饰符keydown keyup
-enter回车
-delete删除/退格
-esc退出
-space空格
-tab换行
-up上
-down下
-left左
-right右
-vue未提供别名的按键,可以使用按键原始的key值去绑定,注意要转为kebab-case(短横线命名caps-lock)
-系统修饰键:ctrl、alt、shift、meta
-配合keyup使用:按下修饰键的同时再按下其他键,随后释放其他键,事件才会被触发
-配合keydown使用:正常触发事件。
-使用keyCode去指定具体按键
-Vue.config.keyCodes.自定义键名=键码,可以定制按键别名
5.计算属性与监听属性
计算属性:
-get、set属性,底层借助了object.defineproperty方法提供的getter和setter。
-当读取计算属性里的值时,get会被调用,初次读取值或者所依赖的数据发生改变时都会被调用。
-有缓存,只有所依赖的数据发生改变时缓存的值才会更新。
-当计算属性的值被直接修改时会执行set
监听属性
-当监视属性变化时,回调函数自动调用,进行相关操作。
-监听属性有两种写法:new Vue里传入watch配置或者通过vm.$watch()监听。
-有handler函数,其身上有旧值与新值(newValue,oldValue)
-没有缓存
-检测data里的属性,也可以监听计算属性里的值
-默认不检测对象内部值的改变,可配置deep:true开启深度监听
区别
-componted无法开启异步任务,watch可以开启异步任务
-componted有缓存机制,watch没有缓存机制
-componted可以完成的功能watch都可以完成,而watch完成的功能componted不一定能完成
-componted的计算结果受其依赖属性的影响,watch的改变可以影响依赖属性。
6.v-if和v-show的区别
-v-show是通过dispaly的属性值来控制元素的显示与隐藏,隐藏后dom元素节点还存在。
-v-if则是通过元素节点的创建与销毁来实现元素的显示与隐藏,隐藏后dom元素节点不存在。
-v-show适用于切换频率比较频繁的场景。
-v-if适用于切换频率比较低的场景。
7.v-for中key的作用
-虚拟dom中,key是唯一标识,当状态中的数据发生变化时,vue会根据新数据生成新的虚拟dom,随后新的虚拟dom与旧的虚拟dom进行差异比较(diff算法)。
-新虚拟dom与旧虚拟dom是通过key进行比较的,如果虚拟dom内容没有发生改变,直接复用之前的真实dom,如果虚拟dom中的内容发生了变化,则生成新的真实dom,随后替换掉页面中对应的旧的真实dom。
-用index索引作为key的话,如果对数据进行逆序添加、逆序删除等破坏顺序的操作,会产生没有必要的真实dom更新,降低效率,如果还有输入类的dom时,会导致界面渲染错误。
-最好将每条数据的唯一标识作为key,如果不存在逆序操作,仅用于列表渲染,可以使用index作为key。
8.vue是如何检测数据的原理(响应式)
<script>
let data=
name:'xxx',
address:'xxx'
//创建一个监视的实例对象
const obs=new Observer(data);
//vm实例对象
let vm=;
vm._data=data=obs;
function Observer(obj)
//汇总对象中的所有属性形成一个数组
const keys=Object.keys(obj);
keys.forEach((k)=>
//this指的是Observer
Object.defineProperty(this,k,
get()
return obj[k];
,
set(val)
obj[k]=val;
)
)
</script>
-vue会监视data中所有层次的数据
-通过setter实现监视,且在new Vue时就传入需要检测的数据。
-对象中后添加的属性,vue不做响应式处理,可以使用Vue.set(target,index,value)或者this.$set()
-对于数组中的数据,默认不监听,可以通过vue提供的push、pop、shift、unshift、splice、sort、reverse对数组的方法进行包装后实现响应式。
9.生命周期
beforeCreate:实例创建之前,初始化事件和数据,无法访问data中的数据和methods中的方法。数据代理未开始
created:实例创建完成,数据和事件已初始化完成,可以访问到data中的数据和methods里的方法。数据监测、数据代理
beforeMounte:实例挂在之前,虚拟dom以准备好,还没有生成真实dom,页面还没有被渲染,对所有的dom操作最终都不生效。
mounted:实例挂载之后,生成了经过vue编译的真实dom,页面被渲染,对dom的操作均有效,初始化过程结束,一般在此开启定时器、发送网络请求、订阅消息、绑定自定义事件等操作。
beforeUpdate:页面更新之前,此时数据是最新的,页面还是旧的,页面和数据尚未保持同步。
updated:页面更新之后,数据时新的,页面也是新的,数据和页面保持同步,完成了model-view的更新。
beforeDestory:实例销毁之前,data里的数据和methods的方法、指令等都可以使用,但操作数据不会触发更新流程,一般在此关闭定时器、解绑自定义事件、取消订阅等操作。
destory:实例销毁之后,自定义事件会失效,但原生的dom事件依然有效。
使用keep-alive缓存后会有路由组件独有的生命周期钩子
actived:被缓存的组件被激活(显示)时使用
deactivated:被缓存的组件失活(隐藏)时使用
特殊的生命周期钩子
$nextTick():在页面下次更新渲染时执行
10.vue中,组件化中data为什么是函数
-避免组件被复用时,数据存在引用关系。
-vue组件可能存在多个实例,如果使用对象形式,会导致多个组件共用一个data,从而使一个组件影响其他组件。
-如果用函数定义,会返回一个全新的对象,避免了组件间之间data的相互影响。
11.组件的创建过程
-组件的本质是一个VueComponent的构造函数,是Vue.extend生成的。每次调用Vue.extend返回的都是一个新的VueComponent。
-非单文件组件
-使用Vue.extend()创建组件
-在vue实例对象中注册组件components:,(全局组件Vue.component()和局部组件)
-使用组件
-单文件组件
-创建组件文件.vue
-使用import引入组件
-在components里注册组件
-使用标签形式使用组件
12.vue脚手架中目录分别是什么意思
-.gitignore git的忽略文件
-babel.config.js babel的配置文件(babel是控制es6转es5)
-package-lock.json 包说明书的缓存文件,用于锁定版本
-package.json 包的说明书
-README.md笔记
-src
-mian.js 整个项目的入口文件
-assets一般存放静态资源,png、视频等
-App.vue跟组件
-components存放除app.vue外的其他组件
-public
-ico图标
-index.html
-node_modules存放第三包的文件夹
render(createElement)
return createElement('h1','xxxx')
13.浏览器的本地存储
-localStorage 浏览器窗口关闭内容不会消失,存储大小一般为5mb,setItem、getItem、remove、clear等api,持久化存储,需要手动清除才会消失,getItem获取不到对应的value会返回null。
-sessionStorage 浏览器窗口关闭,存储的数据会清空,setItem、getItem、remove、clear。
-cookie是一种浏览器管理状态的一个文件,它有name、value,Domain、path等等,数据大小不能超过 4K,是服务器向浏览器发送的一小块数据,不可以跨域请求。设置的cookies过期时间之前一直有效,即使窗口和浏览器关闭,数据会自动地传递到服务器,服务器也可以写cookies到客户端
14.vue组件之间传值
-父组件传值子组件
props
f:<demo :str="str"></demo>
-子组件传父组件
自定义事件的$emit
f:<demo @str="str"></demo>
methods:
demo(e)
c:methods:
handler()
this.$emit('str',this.obj)
通过refs中的$on
f:<demo ref="str"></demo>
mounted:
this.$refs.str.$on('handler',回调函数)
-兄弟组件传值
vuex
全局事件总线$bus
main.js
new Vue(
render:h=>h(App),
beforeCreated()
//安装全局事件总线
Vue.prototyp.$bus=this
).$mount()
在组件中通过this.$bus.$emit('xxx',data)提供数据,通过this.$bus.on('xxx',(data)=>)获取数据。
消息订阅与发布
安装pubsub-js
引入pubsub-js
订阅消息用pubsub.subscribe('xxx',data)
发布消息pubsub.publish('xxx',(msgNmae,data)=>)
14.nextTick
this.$nextTick()
-作用:在下一次dom更新结束之后执行指定回调
-什么时候调用:当改变数据后,要基于更新后的新dom进行某些操作时
15.vue解决跨域
只有浏览器才存在跨域
-cors后端配置响应头,真正意义上的解决跨域
-jsonp立勇<script>的src属性,需要前后端配合,并且只能解决get请求的跨域。
-配置代理服务器
1.nginx
2.利用vue-cli
-devServer:proxy:'目标服务器地址',请求是axios.get('代理服务器地址/xxx/xxx/xx').then((res)=>,(err)=>).cath()
-devServer:
proxy:
'/api':
target:'目标服务器地址',
pathRewrite:'^/api':''
axios.get('代理服务器地址/api/xxx/xxx/xx').then((res)=>,(err)=>).cath()
16.插槽
插槽是让父组件向子组件指定位置插入html结构,也是一种组件通信的方式。
-默认插槽/不具名插槽
c:<solt><solt> f:<child>xxxxxx</child>
子组件中只能定义一个插槽模块
-具名插槽
c:<solt name="demo"></solt> f:<child><div solt="demo">xxx</div></child>
在使用<template></template>标签时可写成
f:<child><template v-solt:demo>xxx</template></child>
-作用域插槽
c:<solt :a='b'></solt>
f:<template scope='c'></template>
或<template slot-scope='c'></template>
作用域插槽是数据在插槽子组件时,无法在插槽使用者父组件中获取得到数据,可以用scope来传递数据,接收时必须用template标签包裹结构。
17.vuex
-vuex是专门在vue中实现集中式状态(数据)管理的vue插件,对vue中多个组件共享状态进行集中式的管理(读/写)。适用于任意组件通信。
-state
存储vue中需要共享的状态(数据),只能在mutations中修改,被修改后会自动更新使用的组件页面。
-actions
提交异步请求,组件通过this.$store.dispatch('行为','值'),可在这里发送请求,之后可以通过commit('行为','值')来提交给mutations,如果不需要向服务器发送请求,可以在组件中通过this.$store.commit('行为','值')来直接提交到mutations里。
xxx(conText,value)
conText.commit('XXX',value)
-mutations
同步操作,可以在此修改state里的值,行为(state,'值')
XXX(state,value)
-getters
state的计算属性,可以在此对state的数据进行加工
xxx(state)
return xxxx
-module
new Vuex.Store(
modules:
a:xxx,
b:xxx
)
computed:
...mapState('a',['xxx'])
需要在每个模块里写namespaced:true
-import mapState from 'vuex'
computed:
...mapState(a:'xxx',b:'xx')
或...mapState(['xxx','xx'])
18.路由
路由切换时,不显示的路由组件被销毁
19.路由传参
-使用router-link时
query传参:<router-link :to="/xxx/xxx?id=xx&name=xxx"></router-link>
<router-link :to="
path:'/xxx/xx',
query:
id:xxx,
name:xxx
">跳转</router-link>
使用this.$route.query.id获取
params传参
<router-link :to="/xxx/xxx/001/sddf"></router-link>
<router-link :to="
name:'asd',
params:
id:xxx,
name:xxx
"></router-link>
-router.js
name:'asd',
path:'xxxx/:id/:name',
component:Detail
接收参数this.$route.params.id
-使用params传参时,若是对象写法,需要在router.js中配置响应的name属性,并且需要占位。
-使用编程式路由导航
this.$router.push(
name:'xxx',
params:
id:xxx,
title:xxx
)
20.keep-alive
-使路由组件在切换时不被销毁
-包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染
21.路由守卫
对路由进行权限控制
router.beforeEach:全局前置路由守卫,to:目标路由,from:来源路由,next():放行;自定义参数需要配置在路由元信息(meta)里配置,用来控制权限。
router.afterEach():全局后置路由守卫,可用于动态更改页面标题。
beforeEnter():单个路由配置,路由独享守卫,对某一个路由进行权限设置。
beforeRouteEnter():组件内置守卫,通过路由规则,进入组件之前调用。
beforeRouteLeave():组件内置守卫,通过路由规则,离开组件之前调用。
22.路由的hash和history
hash:路径中带#,其#后面的参数不会做为路径的一部分发给服务器;若地址通过第三方手机app分享,若app校验严格,地址会被标记为不合法,兼容性比较好。
history:路径中带/,后面的参数不会做为路径的一部分发给服务器;兼容性略差,需要后端去解决页面刷新出现404的问题。
23.vue3的优点
-性能提升
打包大小减少41%
初次渲染快55%,更新渲染快133%
内存减少54%
-源码升级
使用proxy代替defineproperty实现响应式
重写虚拟dom的实现和剔除多余代码(tree-shaking)
-vue3可以更好的支持typescript
-新特性
composition API(组合api)
setup配置
ref与reactive
新的内置组件
fragment
teleport
新的生命周期钩子
移除keycode支持作为v-on的修饰符
data始终是一个函数
24.watchEffect函数和computed的区别
-computed:是计算函数,注重计算出来的值,所以必须写返回值
-watchEffect:是监视函数,注重过程,不用写返回值
vue面试题+答案,2021前端面试
vue面试题+答案,2021前端面试
vue视频教程系列:
Vue3+ElementPlus+Koa2 全栈开发后台系统
试看:点击观看
完整课程:点击查看
Vue3.0高阶实战:开发高质量音乐Web app
试看:点击观看
完整课程:点击查看
VUE全面教学+VUE开源项目超级实战:
试看:点击观看
完整课程:点击查看
最新Vue.JS教程快速入门到项目实战(Vue3/VueJS技术详解)
试看:点击观看
完整课程:点击查看
最新最全前端毕设项目(小程序+VUE+Noed+React+uni app+Express+Mongodb)
试看:点击观看
完整课程:点击查看
MVC 和 MVVM 区别
MVC
MVC 全名是 Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范
- Model(模型):是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据
- View(视图):是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的
- Controller(控制器):是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据
MVC 的思想:一句话描述就是 Controller 负责将 Model 的数据用 View 显示出来,换句话说就是在 Controller 里面把 Model 的数据赋值给 View。
MVVM
MVVM 新增了 VM 类
- ViewModel 层:做了两件事达到了数据的双向绑定 一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。
MVVM 与 MVC 最大的区别就是:它实现了 View 和 Model 的自动同步,也就是当 Model 的属性改变时,我们不用再自己手动操作 Dom 元素,来改变 View 的显示,而是改变属性后该属性对应 View 层显示会自动改变(对应Vue数据驱动的思想)
整体看来,MVVM 比 MVC 精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不用再用选择器操作 DOM 元素。因为在 MVVM 中,View 不知道 Model 的存在,Model 和 ViewModel 也观察不到 View,这种低耦合模式提高代码的可重用性
注意:Vue 并没有完全遵循 MVVM 的思想 这一点官网自己也有说明
那么问题来了 为什么官方要说 Vue 没有完全遵循 MVVM 思想呢?
- 严格的 MVVM 要求 View 不能和 Model 直接通信,而 Vue 提供了$refs 这个属性,让 Model 可以直接操作 View,违反了这一规定,所以说 Vue 没有完全遵循 MVVM。
vue是如何实现响应式数据的呢?(响应式数据原理)
Vue2: Object.defineProperty
重新定义 data
中所有的属性, Object.defineProperty
可以使数据的获取与设置增加一个拦截的功能,拦截属性的获取,进行依赖收集。拦截属性的更新操作,进行通知。
具体的过程:首先Vue使用 initData
初始化用户传入的参数,然后使用 new Observer
对数据进行观测,如果数据是一个对象类型就会调用 this.walk(value)
对对象进行处理,内部使用 defineeReactive
循环对象属性定义响应式变化,核心就是使用 Object.defineProperty
重新定义数据。
那vue中是如何检测数组变化的呢?
数组就是使用 object.defineProperty
重新定义数组的每一项,那能引起数组变化的方法我们都是知道的, pop
、 push
、 shift
、 unshift
、 splice
、 sort
、 reverse
这七种,只要这些方法执行改了数组内容,我就更新内容就好了,是不是很好理解。
- 是用来函数劫持的方式,重写了数组方法,具体呢就是更改了数组的原型,更改成自己的,用户调数组的一些方法的时候,走的就是自己的方法,然后通知视图去更新。
- 数组里每一项可能是对象,那么我就是会对数组的每一项进行观测,(且只有数组里的对象才能进行观测,观测过的也不会进行观测)
vue3:改用 proxy
,可直接监听对象数组的变化。
vue的优点
轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十kb;
简单易学:国人开发,中文文档,不存在语言障碍 ,易于理解和学习;
双向数据绑定:保留了angular的特点,在数据操作方面更为简单;
组件化:保留了react的优点,实现了html的封装和重用,在构建单页面应用方面有着独特的优势;
视图,数据,结构分离:使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作;
虚拟DOM:dom操作是非常耗费性能的,不再使用原生的dom操作节点,极大解放dom操作,但具体操作的还是dom不过是换了另一种方式;
运行速度更快:相比较与react而言,同样是操作虚拟dom,就性能而言,vue存在很大的优势。
为什么vue组件中data必须是一个函数?
对象为引用类型,当复用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改;而使用返回对象的函数,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题。
v-if 和 v-show 的区别
v-if 在编译过程中会被转化成三元表达式,条件不满足时不渲染此节点。
v-show 会被编译成指令,条件不满足时控制样式将对应节点隐藏 (display:none)
为什么Vue采用异步渲染呢?
Vue
是组件级更新,如果不采用异步更新,那么每次更新数据都会对当前组件进行重新渲染,所以为了性能, Vue
会在本轮数据更新后,在异步更新视图。核心思想 nextTick
。
dep.notify()
通知 watcher进行更新, subs[i].update
依次调用 watcher 的 update
, queueWatcher
将watcher 去重放入队列, nextTick( flushSchedulerQueue
)在下一tick中刷新watcher队列(异步)。
父子组件生命周期调用顺序(简单)
渲染顺序:先父后子,完成顺序:先子后父
更新顺序:父更新导致子更新,子更新完成后父
销毁顺序:先父后子,完成顺序:先子后父
用VNode来描述一个DOM结构
虚拟节点就是用一个对象来描述一个真实的DOM元素。首先将 template
(真实DOM)先转成 ast
, ast
树通过 codegen
生成 render
函数, render
函数里的 _c
方法将它转为虚拟dom
diff算法
时间复杂度: 个树的完全 diff
算法是一个时间复杂度为 O(n*3)
,vue进行优化转化成 O(n)
。
理解:
最小量更新,
key
很重要。这个可以是这个节点的唯一标识,告诉diff
算法,在更改前后它们是同一个DOM节点- 扩展
v-for
为什么要有key
,没有key
会暴力复用,举例子的话随便说一个比如移动节点或者增加节点(修改DOM),加key
只会移动减少操作DOM。
- 扩展
- 只有是同一个虚拟节点才会进行精细化比较,否则就是暴力删除旧的,插入新的。
- 只进行同层比较,不会进行跨层比较。
diff算法的优化策略:四种命中查找,四个指针
- 旧前与新前(先比开头,后插入和删除节点的这种情况)
- 旧后与新后(比结尾,前插入或删除的情况)
- 旧前与新后(头与尾比,此种发生了,涉及移动节点,那么新前指向的节点,移动到旧后之后)
- 旧后与新前(尾与头比,此种发生了,涉及移动节点,那么新前指向的节点,移动到旧前之前)
v-for 为什么要加 key
如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速
更准确:因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确。
更快速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快
vue-router 路由钩子函数是什么 执行顺序是什么
路由钩子的执行流程, 钩子函数种类有:全局守卫、路由守卫、组件守卫
完整的导航解析流程:
- 导航被触发。
- 在失活的组件里调用 beforeRouteLeave 守卫。
- 调用全局的 beforeEach 守卫。
- 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
- 在路由配置里调用 beforeEnter。
- 解析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。
- 调用全局的 beforeResolve 守卫 (2.5+)。
- 导航被确认。
- 调用全局的 afterEach 钩子。
- 触发 DOM 更新。
- 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
谈一下对 vuex 的个人理解
vuex 是专门为 vue 提供的全局状态管理系统,用于多个组件中数据共享、数据缓存等。(无法持久化、内部核心原理是通过创造一个全局实例 new Vue)
主要包括以下几个模块:
- State:定义了应用状态的数据结构,可以在这里设置默认的初始状态。
- Getter:允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。
- Mutation:是唯一更改 store 中状态的方法,且必须是同步函数。
- Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。
- Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。
keep-alive 使用场景和原理
keep-alive 是 Vue 内置的一个组件,可以实现组件缓存,当组件切换时不会对当前组件进行卸载。
- 常用的两个属性 include/exclude,允许组件有条件的进行缓存。
- 两个生命周期 activated/deactivated,用来得知当前组件是否处于活跃状态。
- keep-alive 的中还运用了 LRU(最近最少使用) 算法,选择最近最久未使用的组件予以淘汰。
Vue.extend 作用和原理
官方解释:Vue.extend 使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。
其实就是一个子类构造器 是 Vue 组件的核心 api 实现思路就是使用原型继承的方法返回了 Vue 的子类 并且利用 mergeOptions 把传入组件的 options 和父类的 options 进行了合并
Vue组件如何通信?
Vue组件通信的方法如下:
props/$emit+v-on
: 通过props将数据自上而下传递,而通过$emit和v-on来向上传递信息。- EventBus: 通过EventBus进行信息的发布与订阅
- vuex: 是全局数据管理库,可以通过vuex管理全局的数据流
$attrs/$listeners
: Vue2.4中加入的$attrs/$listeners
可以进行跨级的组件通信- provide/inject:以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效,这成为了跨组件通信的基础
还有一些用solt插槽或者ref实例进行通信的,使用场景过于有限就不赘述了。
computed和watch有什么区别?
computed:
computed
是计算属性,也就是计算值,它更多用于计算值的场景computed
具有缓存性,computed的值在getter执行后是会缓存的,只有在它依赖的属性值改变之后,下一次获取computed的值时才会重新调用对应的getter来计算computed
适用于计算比较消耗性能的计算场景
watch:
- 更多的是「观察」的作用,类似于某些数据的监听回调,用于观察
props
$emit
或者本组件的值,当数据变化时来执行回调进行后续操作 - 无缓存性,页面重新渲染时值不变化也会执行
小结:
- 当我们要进行数值计算,而且依赖于其他数据,那么把这个数据设计为computed
- 如果你需要在某个数据变化时做一些事情,使用watch来观察这个数据变化
虚拟DOM的优劣如何?
优点:
- 保证性能下限: 虚拟DOM可以经过diff找出最小差异,然后批量进行patch,这种操作虽然比不上手动优化,但是比起粗暴的DOM操作性能要好很多,因此虚拟DOM可以保证性能下限
- 无需手动操作DOM: 虚拟DOM的diff和patch都是在一次更新中自动进行的,我们无需手动操作DOM,极大提高开发效率
- 跨平台: 虚拟DOM本质上是JavaScript对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如服务器渲染、移动端开发等等
缺点:
- 无法进行极致优化: 在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化,比如VScode采用直接手动操作DOM的方式进行极端的性能优化
虚拟DOM实现原理?
- 虚拟DOM本质上是JavaScript对象,是对真实DOM的抽象
- 状态变更时,记录新树和旧树的差异
- 最后把差异更新到真正的dom中
Vue 初始化页面闪动问题如何解决?
出现该问题是因为在 Vue 代码尚未被解析之前,尚无法控制页面中 DOM 的显示,所以会看见模板字符串等代码。
解决方案是,在 css 代码中添加 v-cloak 规则,同时在待编译的标签上添加 v-cloak 属性:
[v-cloak] { display: none; }
<div v-cloak>
{{ message }}
</div>
Vue-router 路由有哪些模式?
一般有两种模式:
(1)**hash 模式**:后面的 hash 值的变化,浏览器既不会向服务器发出请求,浏览器也不会刷新,每次 hash 值的变化会触发 hashchange 事件。
(2)**history 模式**:利用了 HTML5 中新增的 pushState() 和 replaceState() 方法。这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。
$nextTick 是什么?
Vue 实现响应式并不是在数据发生后立即更新 DOM,使用 vm.$nextTick
是在下次 DOM 更新循环结束之后立即执行延迟回调。在修改数据之后使用,则可以在回调中获取更新后的 DOM。
Vue 中 computed 和 watch 有什么区别?
计算属性 computed:
(1)**支持缓存**,只有依赖数据发生变化时,才会重新进行计算函数;
(2)计算属性内**不支持异步操作**;
(3)计算属性的函数中**都有一个 get**(默认具有,获取计算属性)**和 set**(手动添加,设置计算属性)方法;
(4)计算属性是自动监听依赖值的变化,从而动态返回内容。
侦听属性 watch:
(1)**不支持缓存**,只要数据发生变化,就会执行侦听函数;
(2)侦听属性内**支持异步操作**;
(3)侦听属性的值**可以是一个对象,接收 handler 回调,deep,immediate 三个属性**;
(3)监听是一个过程,在监听的值变化时,可以触发一个回调,并**做一些其他事情**。
action 与 mutation 的区别
mutation
是同步更新,$watch
严格模式下会报错action
是异步操作,可以获取数据后调用mutation
提交最终数据
谈谈对keep-alive的了解
keep-alive 可以实现组件的缓存,当组件切换时不会对当前组件进行卸载。常用的2个属性
include/exclude ,2个生命周期
activated ,
deactivated
Vue 模板编译原理
Vue 的编译过程就是将 template 转化为 render 函数的过程 分为以下三步
第一步是将 模板字符串 转换成 element ASTs(解析器)
第二步是对 AST 进行静态节点标记,主要用来做虚拟DOM的渲染优化(优化器)
第三步是 使用 element ASTs 生成 render 函数代码字符串(代码生成器)
Vue 修饰符有哪些
事件修饰符
- .stop 阻止事件继续传播
- .prevent 阻止标签默认行为
- .capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
- .self 只当在 event.target 是当前元素自身时触发处理函数
- .once 事件将只会触发一次
- .passive 告诉浏览器你不想阻止事件的默认行为
v-model 的修饰符
- .lazy 通过这个修饰符,转变为在 change 事件再同步
- .number 自动将用户的输入值转化为数值类型
- .trim 自动过滤用户输入的首尾空格
键盘事件的修饰符
- .enter
- .tab
- .delete (捕获“删除”和“退格”键)
- .esc
- .space
- .up
- .down
- .left
- .right
系统修饰键
- .ctrl
- .alt
- .shift
- .meta
鼠标按钮修饰符
- .left
- .right
- .middle
Vue性能优化
编码优化:
- 事件代理
keep-alive
- 拆分组件
key
保证唯一性- 路由懒加载、异步组件
- 防抖节流
Vue加载性能优化
- 第三方模块按需导入(
babel-plugin-component
) - 图片懒加载
用户体验
app-skeleton
骨架屏shellap
p壳pwa
SEO优化
- 预渲染
以上是关于2023vue面试题的主要内容,如果未能解决你的问题,请参考以下文章
前端vue2面试题2023前端最新版vue模块,高频17问(上)