2024年最新vue最全知识点,2024年最新字节跳动前端内部面试题

最后

基础知识是前端一面必问的,如果你在基础知识这一块翻车了,就算你框架玩的再6,webpack、git、node学习的再好也无济于事,因为对方就不会再给你展示的机会,千万不要因为基础错过了自己心怡的公司。前端的基础知识杂且多,并不是理解就ok了,有些是真的要去记。当然了我们是牛x的前端工程师,每天像背英语单词一样去背知识点就没必要了,只要平时工作中多注意总结,面试前端刷下题目就可以了。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

为什么 Vuex 的 mutation 中不能做异步操作?

Vuex中所有的状态更新的唯一途径都是mutation,异步操作通过 Action 来提交 mutation实现,这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现 time-travel 了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难。

新增:vuex的action有返回值吗?返回的是什么?

store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise

Action 通常是异步的,要知道 action 什么时候结束或者组合多个 action以处理更加复杂的异步流程,可以通过定义action时返回一个promise对象,就可以在派发action的时候就可以通过处理返回的 Promise处理异步流程

一个 store.dispatch 在不同模块中可以触发多个 action 函数。在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行。

新增:为什么不直接分发mutation,而要通过分发action之后提交 mutation变更状态

mutation 必须同步执行,我们可以在 action 内部执行异步操作

可以进行一系列的异步操作,并且通过提交 mutation 来记录 action 产生的副作用(即状态变更)

常规篇

computed 和 watch 的区别和运用的场景?

computed:是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;

watch:没有缓存性,更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;当我们需要深度监听对象中的属性时,可以打开deep:true选项,这样便会对对象中的每一项进行监听

运用场景:

当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;

当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用watch选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

Vue2.x组件通信有哪些方式?

父子组件通信

事件机制(**父->子props,子->父 o n 、 on、 on、emit)

获取父子组件实例 p a r e n t 、 parent、 parent、children

Ref 获取实例的方式调用组件的属性或者方法

Provide、inject (不推荐使用,组件库时很常用)

兄弟组件通信

Vue.prototype.$bus = new Vue

Vuex

eventBus 这种方法通过一个空的 Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件

跨级组件通信

Vuex

a t t r s 、 attrs、 attrs、listeners

Provide、inject

说一下v-if和v-show的区别

当条件不成立时,v-if不会渲染DOM元素,v-show操作的是样式(display),切换当前DOM的显示和隐藏。

v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;

v-show 则适用于需要非常频繁切换条件的场景。

为什么 v-for 和 v-if 不建议用在一起

当 v-for 和 v-if 处于同一个节点时,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。如果要遍历的数组很大,而真正要展示的数据很少时,这将造成很大的性能浪费

这种场景建议使用 computed,先对数据进行过滤

组件中的data为什么是一个函数?

一个组件被复用多次的话,也就会创建多个实例。本质上,这些实例用的都是同一个构造函数。

如果data是对象的话,对象属于引用类型,会影响到所有的实例。所以为了保证组件不同的实例之间data不冲突,data必须是一个函数。

子组件为什么不可以修改父组件传递的Prop?/怎么理解vue的单向数据流?

Vue提倡单向数据流,即父级props的更新会流向子组件,但是反过来则不行。

这是为了防止意外的改变父组件状态,使得应用的数据流变得难以理解。

如果破坏了单向数据流,当应用复杂时,debug 的成本会非常高。

v-model是如何实现双向绑定的?

v-model是用来在表单控件或者组件上创建双向绑定的

他的本质是v-bind和v-on的语法糖

在一个组件上使用v-model,默认会为组件绑定名为value的prop和名为input的事件

nextTick的实现原理是什么?

在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后立即使用 nextTick 来获取更新后的 DOM。

nextTick主要使用了宏任务和微任务。

根据执行环境分别尝试采用Promise、MutationObserver、setImmediate,如果以上都不行则采用setTimeout定义了一个异步方法,多次调用nextTick会将方法存入队列中,通过这个异步方法清空当前队列。

Vue不能检测数组的哪些变动?Vue 怎么用 vm.$set() 解决对象新增属性不能响应的问题 ?

Vue 不能检测以下数组的变动:

第一类问题

// 法一:Vue.set

Vue.set(vm.items, indexOfItem, newValue)

// 法二:Array.prototype.splice

vm.items.splice(indexOfItem, 1, newValue)

1

2

3

4

第二类问题,可使用 splice:

vm.items.splice(newLength)

1

当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue

当你修改数组的长度时,例如:vm.items.length = newLength

解决办法:

vm.$set 的实现原理是:

如果目标是数组,直接使用数组的 splice 方法触发相应式;

如果目标是对象,会先判读属性是否存在、对象是否是响应式,最终如果要对属性进行响应式处理,则是通过调用 defineReactive 方法进行响应式处理( defineReactive 方法就是 Vue 在初始化对象时,给对象属性采用 Object.defineProperty 动态添加 getter 和 setter 的功能所调用的方法)

Vue事件绑定原理是什么?

原生事件绑定是通过addEventListener绑定给真实元素的,组件事件绑定是通过Vue自定义的$on实现的。

说一下虚拟Dom以及key属性的作用

由于在浏览器中操作DOM是很昂贵的。频繁的操作DOM,会产生一定的性能问题。这就是虚拟Dom的产生原因。

Virtual DOM本质就是用一个原生的JS对象去描述一个DOM节点。是对真实DOM的一层抽象。(也就是源码中的VNode类,它定义在src/core/vdom/vnode.js中。)

虚拟 DOM 的实现原理主要包括以下 3 部分:

用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;

diff 算法 — 比较两棵虚拟 DOM 树的差异;

pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。

key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速,更准确:因为带 key 就不是就地复用了,在 sameNode 函数a.key === b.key对比中可以避免就地复用的情况。所以会更加准确。更快速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快

为什么不建议用index作为key?

不建议 用index 作为 key,和没写基本上没区别,因为不管你数组的顺序怎么颠倒,index 都是 0, 1, 2 这样排列,导致 Vue 会复用错误的旧子节点,做很多额外的工作

生命周期篇

说一下你对Vue的生命周期的理解

简单回答

beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。

keep-alive 有自己独立的钩子函数 activated 和 deactivated。

复杂回答

生命周期 发生了什么

beforeCreate 在当前阶段data、methods、computed以及watch上的数据和方法都不能被访问

created 在实例创建完成后发生,当前阶段已经完成了数据观测,也就是可以使用数据,更改数据,在这里更改数据不会触发updated函数。可以做一些初始数据的获取,在当前阶段无法与Dom进行交互,如果非要想,可以通过vm. n e x t T i c k 来 访 问 D o m b e f o r e M o u n t 发 生 在 挂 载 之 前 , 在 这 之 前 t e m p l a t e 模 板 已 导 入 渲 染 函 数 编 译 。 而 当 前 阶 段 虚 拟 D o m 已 经 创 建 完 成 , 即 将 开 始 渲 染 。 在 此 时 也 可 以 对 数 据 进 行 更 改 , 不 会 触 发 u p d a t e d m o u n t e d 在 挂 载 完 成 后 发 生 , 在 当 前 阶 段 , 真 实 的 D o m 挂 载 完 毕 , 数 据 完 成 双 向 绑 定 , 可 以 访 问 到 D o m 节 点 , 使 用 nextTick来访问Dom beforeMount 发生在挂载之前,在这之前template模板已导入渲染函数编译。而当前阶段虚拟Dom已经创建完成,即将开始渲染。在此时也可以对数据进行更改,不会触发updated mounted 在挂载完成后发生,在当前阶段,真实的Dom挂载完毕,数据完成双向绑定,可以访问到Dom节点,使用 nextTick来访问DombeforeMount发生在挂载之前,在这之前template模板已导入渲染函数编译。而当前阶段虚拟Dom已经创建完成,即将开始渲染。在此时也可以对数据进行更改,不会触发updatedmounted在挂载完成后发生,在当前阶段,真实的Dom挂载完毕,数据完成双向绑定,可以访问到Dom节点,使用refs属性对Dom进行操作

beforeUpdate 发生在更新之前,也就是响应式数据发生更新,虚拟dom重新渲染之前被触发,你可以在当前阶段进行更改数据,不会造成重渲染

updated 发生在更新完成之后,当前阶段组件Dom已完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新

beforeDestroy 发生在实例销毁之前,在当前阶段实例完全可以被使用,我们可以在这时进行善后收尾工作,**比如清除计时器 **

destroyed 发生在实例销毁之后,这个时候只剩下了dom空壳。组件已被拆解,数据绑定被卸除,监听被移出,子实例也统统被销毁

activited keep-alive 专属 组件被激活时调用

deactivated keep-alive 专属 组件被销毁时调用

Vue中组件生命周期调用顺序是什么样的?

组件的调用顺序都是先父后子,渲染完成的顺序是先子后父。

组件的销毁操作是先父后子,销毁完成的顺序是先子后父。

在什么阶段才能访问操作DOM?

在钩子函数 mounted 被调用前,Vue 已经将编译好的模板挂载到页面上,所以在 mounted 中可以访问操作 DOM。

你的接口请求一般放在哪个生命周期中?

可以在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。

但是推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:

能更快获取到服务端数据,减少页面loading 时间;

ssr不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性;

路由篇

vue路由hash模式和history模式实现原理分别是什么,他们的区别是什么?

hash 模式:

#后面 hash 值的变化,不会导致浏览器向服务器发出请求,浏览器不发出请求,就不会刷新页面

通过监听 hashchange 事件可以知道 hash 发生了哪些变化,然后根据 hash 变化来实现更新页面部分内容的操作。

history 模式:

history 模式的实现,主要是 HTML5 标准发布的两个 API,pushState 和 replaceState,这两个 API 可以在改变 url,但是不会发送请求。这样就可以监听 url 变化来实现更新页面部分内容的操作

区别

url 展示上,hash 模式有“#”,history 模式没有

刷新页面时,hash 模式可以正常加载到 hash 值对应的页面,而 history 没有处理的话,会返回 404,一般需要后端将所有页面都配置重定向到首页路由

兼容性,hash 可以支持低版本浏览器和 IE。

路由懒加载是什么意思?如何实现路由懒加载?

路由懒加载的含义:把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件

实现:结合 Vue 的异步组件和 Webpack 的代码分割功能

const Foo = () => Promise.resolve({ /* 组件定义对象 */ })

1

import(’./Foo.vue’) // 返回 Promise

1

结合这两者,这就是如何定义一个能够被 Webpack 自动代码分割的异步组件

const Foo = () => import(’./Foo.vue’)

const router = new VueRouter({ routes: [ { path: ‘/foo’, component: Foo } ]})

1

2

在 Webpack 2 中,我们可以使用动态 import语法来定义代码分块点 (split point)

可以将异步组件定义为返回一个 Promise 的工厂函数 (该函数返回的 Promise 应该 resolve 组件本身)

使用命名 chunk,和webpack中的魔法注释就可以把某个路由下的所有组件都打包在同个异步块 (chunk) 中

chunkconst Foo = () => import(/* webpackChunkName: “group-foo” */ ‘./Foo.vue’)

1

Vue-router 导航守卫有哪些

全局前置/钩子:beforeEach、beforeResolve、afterEach

路由独享的守卫:beforeEnter

组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

进阶篇

说说vue和react的异同

使用 Virtual DOM

提供了响应式 (Reactive) 和组件化 (Composable) 的视图组件。

将注意力集中保持在核心库,而将其他功能如路由和全局状态管理交给相关的库。

在 React 应用中,当某个组件的状态发生变化时,它会以该组件为根,重新渲染整个组件子树(除非使用PureComponent/shouldComponentUpdate),在 Vue 应用中,组件的依赖是在渲染过程中自动追踪的,所以系统能精确知晓哪个组件确实需要被重渲染

在 React 中,一切都是 JavaScript。不仅仅是 HTML 可以用 JSX 来表达,现在的潮流也越来越多地将 CSS 也纳入到 JavaScript 中来处理

Vue 的路由库和状态管理库都是由官方维护支持且与核心库同步更新的。React 则是选择把这些问题交给社区维护,因此创建了一个更分散的生态系统,所以有更丰富的生态系统

Vue 提供了CLI 脚手架,能让你通过交互式的脚手架引导非常容易地构建项目。你甚至可以使用它快速开发组件的原型。React 在这方面也提供了create-react-app,但是现在还存在一些局限性

React Native 能使你用相同的组件模型编写有本地渲染能力的 APP,Vue 和Weex会进行官方合作,Weex 是阿里巴巴发起的跨平台用户界面开发框架,同时也正在 Apache 基金会进行项目孵化,另一个选择是NativeScript-Vue,一个用 Vue.js 构建完全原生应用的NativeScript插件

什么是 mixin ?

Mixin 使我们能够为 Vue 组件编写可插拔和可重用的功能。

如果你希望再多个组件之间重用一组组件选项,例如生命周期 hook、 方法等,则可以将其编写为 mixin,并在组件中简单的引用它。

然后将 mixin 的内容合并到组件中。如果你要在 mixin 中定义生命周期 hook,那么它在执行时将优化于组件自已的 hook。

在 Vue 实例中编写生命周期 hook 或其他 option/properties 时,为什么不使用箭头函数 ?

箭头函数自已没有定义 this 上下文中。

当你在 Vue 程序中使用箭头函数 ( => ) 时,this 关键字病不会绑定到 Vue 实例,因此会引发错误。所以强烈建议改用标准函数声明。

Vue模版编译原理知道吗,能简单说一下吗?

简单说,Vue的编译过程就是将template转化为render函数的过程。会经历以下阶段(生成AST树/优化/codegen):

首先解析模版,生成AST语法树(一种用JavaScript对象的形式来描述整个模板)。使用大量的正则表达式对模板进行解析,遇到标签、文本的时候都会执行对应的钩子进行相关处理。

Vue的数据是响应式的,但其实模板中并不是所有的数据都是响应式的。有一些数据首次渲染后就不会再变化,对应的DOM也不会变化。那么优化过程就是深度遍历AST树,按照相关条件对树节点进行标记。这些被标记的节点(静态节点)我们就可以跳过对它们的比对,对运行时的模板起到很大的优化作用。

编译的最后一步是将优化后的AST树转换为可执行的代码。

diff算法说一下

同级比较,再比较子节点

先判断一方有子节点一方没有子节点的情况(如果新的children没有子节点,将旧的子节点移除)

比较都有子节点的情况(核心diff)

递归比较子节点

说说你对keep-alive组件的了解

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,其有以下特性:

一般结合路由和动态组件一起使用,用于缓存组件;

提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;

对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。

说说你对SSR的了解

SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端

SSR的优势

更好的SEO

首屏加载速度更快

SSR的缺点

开发条件会受到限制,服务器端渲染只支持beforeCreate和created两个钩子

最后

基础知识是前端一面必问的,如果你在基础知识这一块翻车了,就算你框架玩的再6,webpack、git、node学习的再好也无济于事,因为对方就不会再给你展示的机会,千万不要因为基础错过了自己心怡的公司。前端的基础知识杂且多,并不是理解就ok了,有些是真的要去记。当然了我们是牛x的前端工程师,每天像背英语单词一样去背知识点就没必要了,只要平时工作中多注意总结,面试前端刷下题目就可以了。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值