2024年前端最新最新的Vue面试题大全含源码级回答,吊打面试官系列,前端初级面试题

Vue 面试题

1.Vue 双向绑定原理
2.描述下 vue 从初始化页面–修改数据–刷新页面 UI 的过程?
3.你是如何理解 Vue 的响应式系统的?
4.虚拟 DOM 实现原理
5.既然 Vue 通过数据劫持可以精准探测数据变化,为什么还需要虚拟 DOM 进行 diff 检测差异?
6.Vue 中 key 值的作用?
7.Vue 的生命周期
8.Vue 组件间通信有哪些方式?
9.watch、methods 和 computed 的区别?
10.vue 中怎么重置 data?
11.组件中写 name 选项有什么作用?
12.vue-router 有哪些钩子函数?
13.route 和 router 的区别是什么?
14.说一下 Vue 和 React 的认识,做一个简单的对比
15.Vue 的 nextTick 的原理是什么?
16.Vuex 有哪几种属性?
17.vue 首屏加载优化
18.Vue 3.0 有没有过了解?
19.vue-cli 替我们做了哪些工作?

如果你觉得对你有帮助,可以戳这里获取:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

return vm

}

Vue.prototype.$emit = function (event: string): Component {

const vm: Component = this

let cbs = vm._events[event]

// 循环调用要触发的事件的回调函数数组

if (cbs) {

cbs = cbs.length > 1 ? toArray(cbs) : cbs

const args = toArray(arguments, 1)

const info = event handler for "${event}"

for (let i = 0, l = cbs.length; i < l; i++) {

invokeWithErrorHandling(cbs[i], vm, args, vm, info)

}

}

return vm

}

4. attrs、listeners

  • $attrs: 包含了父作用域没被props声明绑定的数据,组件可以通过v-bind="$attrs"继续传给子组件

  • $listernes: 包含了父作用域中的v-on(不含 .native 修饰器的) 监听事件,可以通过v-on="$listeners"传入内部组件

5. provide、inject

父组件通过provide注入一个依赖,其所有的子孙组件可以通过inject来接收。要注意的是官网有这一段话:

提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

所以Vue不会对provide中的变量进行响应式处理。要想 inject 接受的变量是响应式的,provide 提供的变量本身就需要是响应式的。实际上在很多高级组件中都可以看到组件会将this通过provide传递给子孙组件,包括element-ui、ant-design-vue等。

6. vuex 状态管理实现通信

vuex是专为vue设计的状态管理模式。每个组件实例都有共同的store实例,并且store.state是响应式的,改变state唯一的办法就是通过在这个store实例上commit一个mutation,方便跟踪每一个状态的变化,实现原理在下面的vuex原理里有讲。

8.computed、watch、method有什么区别


computed:有缓存,有对应的watcher,watcher有个lazy为true的属性,表示只有在模板里去读取它的值后才会计算,并且这watcher在初始化的时候会赋值dirty为true,watcher只有dirty为true的时候才会重新求值,重新求值后会将dirty置为false,false会直接返回watcher的value,只有下次watcher的响应式依赖有更新的时候,会将watcher的dirty再置为false,这时候才会重新求值,这样就实现了computed的缓存。

watch:watcher的对象每次更新都会执行函数。watch 更适用于数据变化时的异步操作。如果需要在某个数据变化时做一些事情,使用watch。

method: 将方法在模板里使用,每次视图有更新都会重新执行函数,性能消耗较大。

9.生命周期


官网对生命周期的说明:

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

生命周期就是每个Vue实例完成初始化、运行、销毁的一系列动作的钩子。

基本上可以说8 个阶段创建前/后,载入前/后,更新前/后,销毁前/后。

  • 创建前/后: 在 beforeCreate 阶段,vue 实例的挂载元素 el 还没有。

  • 载入前/后:在 beforeMount 阶段,vue 实例的$el 和 data 都初始化了,但还是挂载之前为虚拟的 dom 节点,data.message 还未替换。在 mounted 阶段,vue 实例挂载完成,data.message 成功渲染。

  • 更新前/后:当 data 变化时,会触发 beforeUpdate 和 updated 方法。

  • 销毁前/后:在执行 destroy 方法后,对 data 的改变不会再触发周期函数,说明此时 vue 实例已经解除了事件监听以及和 dom 的绑定,但是 dom 结构依然存在

结合源码再理解,在源码中生命周期钩子是用callHook函数调用的。看下callHook函数:

function callHook (vm: Component, hook: string) {

pushTarget()

const handlers = vm.$options[hook]

const info = ${hook} hook

if (handlers) {

for (let i = 0, j = handlers.length; i < j; i++) {

invokeWithErrorHandling(handlers[i], vm, null, vm, info)

}

}

if (vm._hasHookEvent) {

vm.$emit(‘hook:’ + hook)

}

popTarget()

}

接收一个vm组件实例的参数和hook,取组件实例的$options传入的hook属性值,有的话会循环调用这个钩子的回调函数。在调用生命钩子的回调函数之前会临时pushTarget一个null值,也就是将Dep.target置为空来禁止在执行生命钩子的时候进行依赖收集。

vm.$emit(‘hook:’ + hook)则是用来给父组件监听该组件的回调事件。

接下来看每个生命钩子具体调用的时机。

1. beforeCreate、created:

Vue.prototype._init = function (options?: Object) {

initLifecycle(vm)

initEvents(vm)

initRender(vm)

callHook(vm, ‘beforeCreate’)

initInjections(vm) // resolve injections before data/props

initState(vm)

initProvide(vm) // resolve provide after data/props

callHook(vm, ‘created’)

if (vm.$options.el) {

vm. m o u n t ( v m . mount(vm. mount(vm.options.el)

}

}

在执行beforeCreate之前调用了 initLifecycle、initEvents、initRender函数,所以beforeCreate是在初始化生命周期、事件、渲染函数之后的生命周期。

在执行created之前调用了initInjections、initState、initProvide,这时候created初始化了data、props、watcher、provide、inject等,所以这时候就可以访问到data、props等属性。

2. beforeMount、mounted

3. beforeUpdate、updated

这两个钩子函数是在数据更新的时候进行回调的函数。在src/core/instance/lifecycle.js找到beforeUpdate调用的代码:

new Watcher(vm, updateComponent, noop, {

before () {

if (vm._isMounted && !vm._isDestroyed) {

callHook(vm, ‘beforeUpdate’)

}

}

}, true /* isRenderWatcher */)

_isMounted为ture的话(DOM已经被挂载)会调用callHook(vm, ‘beforeUpdate’)方法,然后会对虚拟DOM进行重新渲染。然后在/src/core/observer/scheduler.js下的flushSchedulerQueue()函数中渲染DOM,flushSchedulerQueue会刷新watcher队列并执行,执行完所有watcher的run方法之后(run方法就是watcher进行dom diff并更新DOM的方法),再调用callHook(vm, ‘updated’),代码如下:

/**

  • Flush both queues and run the watchers.

*/

function flushSchedulerQueue () {

for (index = 0; index < queue.length; index++) {

watcher = queue[index]

if (watcher.before) {

watcher.before()

}

watcher.run()

}

callUpdatedHooks(updatedQueue)

}

function callUpdatedHooks (queue) {

let i = queue.length

while (i–) {

const watcher = queue[i]

const vm = watcher.vm

if (vm._watcher === watcher && vm._isMounted && !vm._isDestroyed) {

callHook(vm, ‘updated’)

}

}

}

4. beforeDestroy、destroyed

这两个钩子是vue实例销毁的钩子,定义在Vue.protot

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值