作为一个程序员如果你想要找到你心仪的工作,不可避免的就会问到很多八股文,虽然有的和工作没有半毛钱关系,但是你如果想要通过面试还必须得会。所以我最近开始总结一些面试题,一是为了加强自己的理解能够找到一份好的工作,二是为了尽可能的帮助更多的小伙伴能够快速掌握相关知识或者顺利通过面试?。
本篇文章介绍了一些vue的常见问题。我尽量将这些问题根据难易程度,相关联度进行排列使其更好的过度与理解。当然本篇文章不仅仅是八股文那么简单,工作中经常也会经常用到这些知识点。
这个问题一般问的不多,但是如果问到了你就必须得答出来
回答
| Vue2(选项式API) | Vue3(setup) | 描述 |
|---|---|---|
| beforeCreate | - | 实例创建前 |
| created | - | 实例创建后 |
| beforeMount | onBeforeMount | DOM挂载前调用 |
| mounted | onMounted | DOM挂载完成调用 |
| beforeUpdate | onBeforeUpdate | 数据更新之前被调用 |
| updated | onUpdated | 数据更新之后被调用 |
| beforeDestroy | onBeforeUnmount | 组件销毁前调用 |
| destroyed | onUnmounted | 组件销毁完成调用 |
这个相对于上一个问题稍微复杂一点,可以试着理解记忆或者直接记住吧
渲染过程
更新过程
销毁过程
注意
如果子组件是异步组件的话它们的执行顺序会发生改变,会先执行完父组件的生命周期然后再执行子组件的生命周期
这个问题算是非常基本的题了,它也很好理解,面试一般会问这两个指令的区别是什么,以及在什么场景下分别用哪个指令合适
回答
v-if表示一个dom元素是否被创建,而v-show则是控制这个dom元素的display属性是否为nonev-show,v-if则更适合条件不经常改变的场景,因为它切换开销相对较大这个问题被问到的频率还是比较高的,虽然它在实际开发中并不会这么用。
回答
computed和watch实际工作中用的比较多,所以问的也比较多,一般理解了基本都能回答上来
<template>
<div>{{ addSum }}</div>
<div>{{ addSum }}</div>
<div>{{ addSum }}</div>
</template>
<script setup>
import { computed, ref, watch } from "vue";
const a = ref(1)
const b = ref(2)
let addSum = computed(() => {
console.log('内部逻辑执行')
return a.value + b.value
})
</script>
页面多次使用addSum,但是只会打印一次"内部逻辑执行"
immediate:true首次才会执行监听deep:true才会进行深度监听关于vue-router能问的问题非常多,比如它的实现原理,路由跳转,路由守卫等等,所以建议去系统的查看vue-router文档
问题1:vue-router是什么,描述一下它的原理?
Vue Router是Vue官方的路由管理器,有hash和history两种模式
hash模式是通过监听hashchange事件来实现更新页面部分内容的操作,url后面会带有#号
history模式则是通过监听popstate事件来实现更新页面部分内容的操作原理和hash模式差不多,只不过url后面不会出现#会显得更加美观。同时会带来一个问题,因为没有#号,所以当用户刷新页面时会向服务器发请求导致请求资源为404,因此需要对nginx进行一个配置,需要把所有路由都重定向到根页面
问题2:路由跳转方式有哪些?
router.push({ path: '/home' }),router.replace({ path: '/home' })问题3:说一下路由守卫?
路由守卫分为全局路由守卫,路由独享守卫,组件路由守卫
beforeEach,接收to、from、next三个参数,每个路由跳转前都会触发,登录验证时用的比较多beforeResolve,和beforeEach类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后调用beforeEnter,一般配置在路由配置文件中(router/index.js),对进入某个路由之前进行相关操作
接收
to、from、next三个参数
beforeRouteEnter,进入该组件之前调用,无法获取到vue实例
beforeRouteUpdate,在当前路由改变,但是该组件被复用时调用
beforeRouteLeave, 在离开当前组件时调用
当面试问你会用vue3吗,如果你回答会用的话,那么大概率会问vue2和vue3有哪些区别,最近我去面试的时候百分之90都问了这个问题。
回答
options(选项)Api,vue3的是composition Api(当然vue3也兼容composition api)。options Api中methods,compute,data等api都是分散的。而composition api中的代码是根据逻辑功能来组织的,我们可以将一个功能所定义的methods,compute,data等api会放在一起,让我们可以更灵活地组合组件逻辑。ref和reactive将数据声明为响应式Object.defineProperty对数据劫持实现的,vue3中则是使用Proxy对数据代理实现的。beforeCreate和created合并到了setup函数中Teleport和异步依赖处理组件Suspense面试一般会问你如何写一个vue插件,所以没写过vue插件的最好去亲自体验一下
回答:
vue实例会有一个use函数,它接受的是一个带有install函数的对象和一个可选的选项对象,当我们使用 vue.use(plugin)或者app.use(plugin)会调用我们插件的install属性的函数,并且将当前组件的实例传进来.所以在插件中就可以对这个实例进行一些操作来实现我们插件的功能
插槽slot可以理解为占坑,当使用一个组件的时候,在组件标签里的对应的内容就会替换掉这个组件中的slot标签。
插槽分为默认插槽,具名插槽,作用域插槽。
默认插槽
子组件中用slot标签来确定渲染位置,父组件使用它时直接在子组件的标签内写入内容即可
//子组件
<template>
<slot />
</template>
//父组件
<Child>
<div>默认插槽</div>
</Child>
具名插槽
顾名思义就是具有名字的插槽,子组件中可以用name熟悉对slot命名,父组件在使用的时候通过
template中的v-slot:name或者#name来定义这个插槽中的内容
//子组件
<template>
<slot name="content"></slot>
</template>
//父组件
<Child>
<template v-slot:content>具名插槽内容</template>
</Child>
作用域插槽
子组件中的slot可以通过类似组件属性传递的方式将子组件的值传递给父组件中这个子组件的插槽内容中(子组件标签内),在父组件使用子组件的时候要用v-slot的值进行接收这些参数,默认插槽可以将其直接写在子组件标签上,具名插槽则写在template上。而传过来的值只能在子组件标签中或者template标签中使用。所以在父组件作用域中获取到了子组件作用域中的变量,可以认为作用域插槽延伸了子组件数据的作用范围,因此叫做作用域插槽
如果你想详细理解插槽的作用可以阅读这篇文章Vue3中插槽(slot)用法汇总 - 掘金 (juejin.cn)
这里我大概归纳了一下vue2和vue3的传参方式
| 方式 | Vue2 | Vue3 |
|---|---|---|
| 父传子 | props | props |
| 子传父 | $emit | emits |
| 父传子 | $attrs | attrs |
| 子传父 | $listeners | 无(合并到 attrs方式) |
| 父传子 | provide/inject | provide/inject |
| 子组件访问父组件 | $parent | 无 |
| 父组件访问子组件 | $children | 无 |
| 父组件访问子组件 | $ref | expose&ref |
| 兄弟组件传值 | EventBus | mitt |
它们的具体用法可以参考我的这篇文章盘点Vue2和Vue3的10种组件通信方式(值得收藏) - 掘金 (juejin.cn)
除了上面的传参方式你也可以回答Vuex和Pinia,前提你了解这两个状态管理器,因为你说了大概率下个问题就会问你Vuex和Pinia
面试问到这个问题的时候,不要上来就开始说什么state,mutation...。你要先阐述Vuex干嘛用的,什么时候需要用Vuex。
回答
state,mutations,actions,其中state为存放数据的地方,mutations中的函数作用则是用来修改state,actions中一般是用了处理一些异步操作的函数。getters,moudles,getters就像Vue中的计算属性computed一样用来描述依赖响应式状态state中的复杂逻辑。moudles则是可以将store分割成模块(module),每个模块都拥有自己的state,mutations,actions等,在大型应用中经常用到actions中进行数据请求,拿到结果通过它的dispatch方法调用mutations中修改state的函数,从而将结果赋值给了state这个现在问的好像不多,从我最近面试来看只有我提到了才会问一下,但是以后问的肯定会越来越多。关于pinia问的一般是它和Vuex的区别,确切的说应该是它和Vuex4之间的区别
回答
pinia其实就是Vuex5,它和Vuex的主要区别有以下几点
Pinia使用更简单,更符合开发者的开发习惯
pinia中没有了mutations,状态state的修改可以直接进行修改,或者在actions中修改,或者使用它的$patch方法进行修改
pinia中没有了modules,如果想使用多个store,直接使用defineStore定义多个store传入不同的id即可
更好的TS支持,不需要创建自定义的复杂包装器来支持TS
vue 官方提供了v-text、v-for、v-model、v-if 等常用的指令。除此之外vue 还允许开发者自定义指令。面试经常会问什么是自定义指令?你用自定义指令做过哪些功能?
回答1:什么是自定义指令?
directives选项注册。局部指令指在某个组件中注册,而全局则是将指令注册到全局,通常在main.js中注册。created,beforeMount,mounted,beforeUpdate,updated,beforeUnmount,unmounted,mounted 和 updated,它接受el,binding等参数.binding参数的值一般包含绑定到这个元素上的信息,比如下面这个指令<div v-example:foo.bar="baz">
它的binding会是这个对象
{
arg: 'foo',
modifiers: { bar: true },
value: /* `baz` 的值 */,
oldValue: /* 上一次更新时 `baz` 的值 */
}
回答2:你用自定义指令做过哪些功能?
官网描述
<KeepAlive>是一个内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例。
回答
<KeepAlive>将其包裹的话这个组件就会被缓存,当这个组件再一次被显示时就会保留之前的状态。keep-alive接收两个属性include 和 exclude,分别代表哪些组件要用缓存和哪些不需要缓存,它接收组件的名字数组,字符串或者正则,当我们使用动态组件component或者路由router-view的时候可以使用keep-alive还接收max属性表示最大缓存实例数,如果超出这个数则最久没有被访问的缓存实例将被销毁。keep-alive有两个生命周期,分别是activated和deactivated,activated钩子会在首次挂载或者每次从缓存中被重新插入的时候调用。deactivated钩子则是在组件从DOM上移除或者组件卸载时调用vue3中已经没有Mixin这个概念了,所以未来被问到的几率会越来越小,但是目前被问到的频率还是很高的。一般会它的概念以及优缺点,有时还会问它与父组件的生命周期执行顺序
vue官网描述:
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
回答
1.Mixin的作用将组件的公共逻辑提取出来,哪个组件需要用到时,直接将提取的这部分混入到组件内部即可
2. Mixin的生命周期会在父组件生命周期之前执行,如果Mixin中的属性或者方法与父组件冲突则会使用父组件中的
2. 优点:可以降低代码冗余提高逻辑复用性。
3. 缺点:命名容易冲突,不好追溯源,后期排查不方便
这道题问道的频率极高,就我经历的多场面试几乎都会问到,而且是面试到vue方面的开门题。
下面是我自己的理解回答,以vue2为例,大家可以借鉴参考
vue的响应式原理是根据Object.defineProperty这个api来对数据进行劫持并结合发布者-订阅者模式实现的
首先会利用Object.defineProperty中的get函数来对vue中的data的所有属性进行访问劫持,中间会涉及到劫持data中更深层次的属性需要递归调用劫持方法。这里是通过一个Observer类实现的
劫持到每一个属性后会给这个属性绑定多个订阅者watcher,因为一个属性可能被用在很多地方;而这个watcher中则包含更新视图的函数update。
watcher和属性的对应关系以及和视图的联系则是通过编译模板Compile类来实现的。Compile中会拿到整个dom对象,然后遍历元素子节点获取到使用过vue中data属性的则给该属性直接添加一个watcher并赋予一些更新当前视图的方法.
每个属性的多个订阅者watcher都会被添加到对应的数组中,这里则是通过Deps类实现的,初始化watcher的时候会调用Deps中的addSub方法将对应watcher添加该类的Subs数组中
当data中的某个属性发生改变时则会触发Object.defineProperty中的set函数,这时便会调用该属性的Deps类中的notify函数遍历Subs数组中的订阅者watcher并调用其函数update去触发视图的更新
一般问完响应式原理可能会问这两者的区别
回答
Object.defineProperty 只能代理属性,Proxy 代理的是对象。Proxy可以监听到,Object.defineProperty不能。Object.defineProperty 的代理行为是在破坏原对象的基础上实现的,Proxy 则不会破坏原对象,只是在原对象上覆盖了一层。Proxy可以监听到,Object.defineProperty不能。Proxy不兼容IE11及以下vue3新增了两个内置组件分别是Teleport和Suspense。
Teleport组件可以称之为传送门,作用将其插槽内容渲染到 DOM 中的另一个位置,接收两个参数to(要去的位置)和disabled(是否留在原位置)。接收比如下面代码
<teleport to="#popup">
<video src="./my-movie.mp4">
</teleport>
video将会被传送到id为popup的元素下。
Suspense组件<Suspense> 组件用于协调对组件树中嵌套的异步依赖的处理。<Suspense> 组件有两个插槽:#default 和 #fallback,在初始渲染时,<Suspense> 将在内存中渲染其默认的插槽内容。如果在这个过程中遇到任何异步依赖,则会进入挂起状态等待异步组件加载完毕。在挂起状态期间,展示的是 #fallback插槽内容关于nextTick会问到它的用法,然后是它的原理,然后还可能问到JS的时间循环机制。
问题1:vue中的nextTick是干什么用的?
这个其实比较简单,用过都知道它是干嘛的,vue官方的解释是:
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
这是什么意思呢,其实vue中修改data不会立刻触发dom更新;而是把需要更新的Watcher加入到queueWatcher队列中,然后在合适的时机在nextTick中调用这些Watcher的更新函数进行dom更新,所以在data刚被修改的时候,我们是获取不到更新后的dom的,这时候便需要调用nextTick函数在它的回调函数中获取到变化后的dom
问题2:nextTick原理
setImmediate、setTimeout开启一个宏任务执行callbacks问题3:js事件循环机制
不属于vue,后面文章再介绍
这题在工作中有用吗是???答案是没有用,但是在面试中有用啊,所以我们要会回答?
问题1:什么是虚拟dom?
简单来说就是一个描述dom结构的js对象
问题2:为什么要用虚拟dom?
DOM时,浏览器会从头开始进行DOM树的构建,频繁的操作DOM开销是很大的。DOM就是为了减少这些操作的,虚拟DOM首先会通过状态生成一个虚拟节点树(js对象),然后使用虚拟节点树进行渲染。当某些状态发生变更时会生成新的虚拟DOM节点树,然后与上一次虚拟DOM节点树进行比较(diff),从而找到差异的部分,最后渲染到真实的DOM节点上面问题3:说一下diff算法
diff算法的本质是找出两个对象之间的差异,目的是尽可能复用节点。在vue中是当状态发生改变,用来计算改变后的虚拟DOM与改变前的虚拟DOM之间的差异的算法。
具体实现不是几句话就能说清楚的,推荐一篇文章聊聊 Vue 的双端 diff 算法 - 掘金 (juejin.cn)
以上问题基本都是查阅部分资料结合自己的理解总结而来,所以难免会有一些错误以及不妥之处,如果你发现了还希望不吝指出,万分感谢。
最后,创作不易,如果这篇文章对你有所帮助,还希望给个赞?鼓励一下作者吧!
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类
参考文章搭建文章gitte源码在线体验可以注册两个号来测试演示图:一.整体介绍 介绍SignalR一种通讯模型Hub(中心模型,或者叫集线器模型),调用这个模型写好的方法,去发送消息。 内容有: ①:Hub模型的方法介绍 ②:服务器端代码介绍 ③:前端vue3安装并调用后端方法 ④:聊天室样例整体流程:1、进入网站->调用连接SignalR的方法2、与好友发送消息->调用SignalR的自定义方法 前端通过,signalR内置方法.invoke() 去请求接口3、监听接受方法(渲染消息)通过new signalR.HubConnectionBuilder().on
提供3种Ubuntu系统安装微信的方法,在Ubuntu20.04上验证都ok。1.WineHQ7.0安装微信:ubuntu20.04安装最新版微信--可以支持微信最新版,但是适配的不是特别好;比如WeChartOCR.exe报错。2.原生微信安装:linux系统下的微信安装(ubuntu20.04)--微信适配的最好,反应最快,但是微信版本只到2.1.1,版本太老,很多功能都没有。3.深度deepin-wine6安装微信:ubuntu20.04+系统deepin-wine6安装新版微信--综合比较好,当前个人使用此种方法1个月,微信版本3.4;没什么大问题,尚可。一、WineHQ7.0安装微信
我正在尝试为自己创建一个直接连接到我的日历的应用程序……但我从不想参与重新验证。我只想编写一次身份验证代码并完成它。授权码如下:key=Google::APIClient::PKCS12.load_key(SERVICE_ACCOUNT_PKCS12_FILE_PATH,PASSWORD)asserter=Google::APIClient::JWTAsserter.new(SERVICE_ACCOUNT_EMAIL,'https://www.googleapis.com/auth/calendar',key)@client=Google::APIClient.new@client.a
我正在尝试从使用RubyonRails的散列创建http参数,我尝试使用URI.encode_www_form(params),但这没有正确生成参数。下面是我的哈希值params['Name'.to_sym]='NiaKun'params['AddressLine1'.to_sym]='AddressOne'params['City'.to_sym]='CityName'这个方法把空格转成+,我要的是把空格转成%20我收到"Name=Nia+Kun&AddressLine1=Address+One&City=City+Name"但我需要将此空格转换为%20
?作者主页:静Yu?简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者?社区地址:前端知识交流社区?博主的个人博客:静Yu的个人博客?博主的个人笔记本:前端面试题个人笔记本只记录前端领域的面试题目,项目总结,面试技巧等等。接下来会更新蓝桥杯官方系统基础练习的VIP试题,依然包括解题思路,源代码等等。问题描述:给定当前的时间,请用英文的读法将它读出来。时间用时h和分m表示,在英文的读法中,读一个时间的方法是: 如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“threeo’clock”。 如果m不为0,则将时读出来,然后将分读出来,如5
平时开发中我们经常会遇到这样的需求,在一个不限高度的盒子中会有很多内容,如果全部显示用户体验会非常不好,所以可以先折叠起来,当内容达到一定高度时,显示展开更多按钮,点击即可显示全部内容,先来看看效果图: 这样做用户体验瞬间得到提升,接下来看看具体细节。0">主要操作在内容这里{{item.username}},……展开更多样式大家可依据自己项目需求进行设计,这里就不贴了,主要说几个关键的。1、在data中定义三个属性isShowMore:false, //控制展开更多的显示与隐藏textHeight:null, //框中内容的高度status:false, //内容状态是否打开2.计算内容是否
这里写自定义目录标题一、问题二、解决三、解决方案四、打包预览一、问题在使用vue3.2和vite2开发一个移动端或者钉钉端H5微服务iosapp内置浏览器打开没问题安卓app内置浏览器打开空白页面vconsole打印出现报错globalthisundefind二、解决内置浏览器版本比较低打印出来是63vue3代码不兼容低版本浏览器三、解决方案步骤一:vite.config.ts里build.target配置项指定构建目标为es2015或者步骤二:安装@vitejs/plugin-legacy安装完报错也还在指定版本可以解决“@vitejs/plugin-legacy”:“1.8.0”,步骤三: