目录
常见笔试面试题:
Q:vue几种常用的指令
A:v-for 、 v-if 、v-show、v-bind、v-on
Q:v-if 和 v-show 区别
A:v-if按照条件是否渲染,v-show是display的block或none,会一直存在于DOM。v-if是动态创建和销毁元素,因此对性能的影响较大,不适合频繁切换条件。
Q:css只在当前组件起作用
A:在style标签中写入scoped即可 例如:<style scoped></style>
Q:vue常用的修饰符?
A:
.prevent | 阻止事件的默认行为,相当于event.preventDefault() |
.stop | 阻止单击事件冒泡,相当于event.stopPropagation() |
.self | 只当事件是从绑定元素本身触发时才触发处理函数 |
.capture | 用于v-on指令,添加事件监听器时使用事件捕获模式而不是冒泡模式 |
.once | 用于v-on指令,事件只触发一次 |
.passive | 告诉浏览器不要阻止默认行为,适用于需要优化性能的场景。 |
按键修饰符,.enter等 | v-on在键盘事件时,监听特定的键 |
输入修饰符.number | 用于v-model,在用户的输入自动转为数值类型 |
输入修饰符.trim | 用于v-model,自动过滤用户输入的首尾空白字符。 |
输入修饰符.lazy | 将 v-model 的更新延迟到 change 事件触发时 |
v-once 指令的使用场景有哪些?
v-once 指令用于只渲染元素或组件一次,适用于那些不需要在数据变化时更新的静态内容,可以用来优化性能,避免不必要的重新渲染。
Q:v-for和v-if 可以在同一个标签内使用吗?有什么问题?
A:可以但不推荐
- Vue3.0:
v-if
比v-for
的优先级更高,这意味着v-if
的条件将无法访问到v-for
作用域内定义的变量别名。- Vue2.0:
v-for
的优先级比v-if
高,会先循环,再判断,造成性能浪费。
Q:vue中 key 值的作用?
A:key
值主要用于给每个节点的唯一标识,Vue在更新时,它会基于key
值来跟踪每个节点,从而重用和重新排序现有元素,而不是销毁并重新创建它们。使用key
值可以提高渲染性能,尤其是在处理大型列表或频繁更新的列表。
在 Vue.js 中,
key
属性是一个非常重要的概念,尤其是在处理列表渲染和组件复用时。key
的主要目的是帮助 Vue.js 识别不同的 VNode(虚拟 DOM 节点),从而更高效地更新和重用这些节点。下面是key
的几个关键作用和使用场景:1. 唯一标识 VNode
key
的主要作用是作为一个唯一的标识符,用来唯一地标识每一个 VNode。- 当 Vue.js 渲染列表或组件时,它会使用
key
来跟踪每个节点的身份,从而确定哪些节点被创建、更新或销毁。2. 提升性能
- Vue.js 在更新列表时,会比较新旧 VNode 的
key
值,以确定哪些节点需要更新。- 如果没有提供
key
,Vue.js 会通过索引来进行比较,这可能导致不必要的重新渲染和组件实例的销毁重建,降低性能。- 提供了
key
后,Vue.js 可以更准确地识别哪些节点需要移动或更新,从而提高渲染性能。3. 状态保留
- 当你在一个列表中使用具有
key
的组件时,即使列表项的位置发生了变化,组件的状态也会被保留。- 如果不使用
key
,Vue.js 可能会认为位置变化的组件是全新的,从而销毁原有的组件实例并重新创建,导致状态丢失。4. 避免警告
- 如果在列表渲染中不使用
key
,Vue.js 会发出警告,提示你为列表项添加key
。- 这是因为 Vue.js 认为没有
key
的列表渲染可能会导致性能问题或意料之外的行为。
Q:什么是vue的计算属性?
A:定义一个属性,这个属性的值是基于其他属性值的计算结果。是一种高效处理数据依赖和复杂的数据变换的方式。因为在模板中放入太多的计算逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。
计算属性的特点
- 依赖其他属性:计算属性可以依赖于一个或多个其他属性的值。
- 缓存结果:计算属性的结果会被缓存起来,当相关依赖属性没有发生变化时,计算属性的结果不会重新计算,而是直接使用缓存的结果。
- 自动侦测变化:当依赖的属性发生变化时,计算属性会自动重新计算。
- 只读属性:计算属性默认是只读的,如果需要修改计算属性的值,需要使用 setter 或者直接修改依赖属性的值。
为什么要使用 ref?
当你在模板中使用了一个 ref,然后改变了这个 ref 的值时,Vue 会自动检测到这个变化,并且相应地更新 DOM。这是通过一个基于依赖追踪的响应式系统实现的。当一个组件首次渲染时,Vue 会追踪在渲染过程中使用的每一个 ref。然后,当一个 ref 被修改时,它会触发追踪它的组件的一次重新渲染。
什么是refs,有什么用?
refs
是一个特殊的属性,用于引用 Vue 实例中的子组件或 DOM 元素。通过在子组件或 DOM 元素上添加ref
属性,你可以在 Vue 实例中通过$refs
对象来访问这些引用。
什么是slot(插槽) ?
在某些场景中,我们可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段,这个时候我们就可以使用slot。
Vue 中的 nextTick 是做什么的?
nextTick 是一个 Vue 实例的方法,用于在 DOM 更新完成后执行回调函数,如果在数据更改后需要立即获取新的 DOM 元素位置时,可以使用 nextTick。
Vue 3.x 中有哪些新特性?
Composition API:一种新的API,用于更灵活地组织和重用组件逻辑。
Teleport:允许将一个元素“传送”到 DOM 树中的另一个位置。
Suspense:用于处理异步组件的加载状态。
Fragment:允许组件渲染多个根元素。
Composition API有什么好处?
写法更简洁灵活,和TypeScript更配。
如何在 Vue 中实现服务端渲染 (SSR)?
- 使用 Vue.js 官方支持的 SSR 解决方案,例如 Nuxt.js。
- 或者手动设置服务器端渲染流程,使用 vue-server-renderer 库。
- 服务器端渲染可以提高首屏加载速度和搜索引擎优化(SEO)。
Q:$route和$router的区别
A:$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。而$router是“路由实例”对象包括了路由的跳转方法,钩子函数等。
Q:怎么定义 vue-router 的动态路由? 怎么获取传过来的值
A:在 router 目录下的 index.js 文件中,对 path 属性加上 /:id,使用 router 对象的 params.id 获取。
Q:vue.js的两个核心是什么?
A:数据驱动、组件系统
Q:vue等单页面应用及其优缺点
A:优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。
缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退 (引入vue router)。
对于MVVM的理解?
MVVM 是 Model-View-ViewModel 的缩写。
Model:数据模型,可以在Model中定义数据修改和操作的业务逻辑。
View:视图,它负责将数据模型转化成UI 展现出来。
ViewModel: 视图模型,监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个连接View 和 Model的中转站。
在MVVM架构下,View 和 Model 之间并没有直接的联系,ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
Vue的生命周期
beforeCreate(创建前)此阶段为实例初始化之后,此时的数据观察和事件机制都未形成,不能获得DOM节点。
created(创建后) 在这个阶段vue实例已经创建,已完成数据监测、属性和方法的运算、data和事件的初始化,但$el属性还没有显示出来,所以仍然不能获取DOM元素。
beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成编译模板,把data里面的数据和模板生成html,但此时还没有挂载html到页面上,所以在这一阶段,我们依然得不到具体的DOM元素。
mounted(载入后) 在这个阶段,el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用,数据和DOM都已被渲染出来。一般的异步请求都写在这里。
beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
destroyed(销毁后) 在实例销毁之后调用。此时所有的事件监听器、子实例都被移除销毁。
vue的生命周期的思想贯穿在组件开发的始终,通过熟悉其生命周期调用不同的钩子函数,可以准确地控制数据流和其对DOM的影响;vue生命周期的思想是Vnode和MVVM的生动体现和继承。
Question:
Q:什么是Vue生命周期?
A: Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。
Q:Vue生命周期的作用是什么?
A:Vue生命周期提供了多个钩子函数,让开发者准确地控制数据流和其对DOM的影响。
Q:第一次页面加载会触发哪几个钩子?
A:会触发 下面这几个beforeCreate, created, beforeMount, mounted 。
Q:DOM 渲染在 哪个周期中就已经完成?
A:DOM 渲染在 mounted 中就已经完成了。
Vue实现数据双向绑定的原理
Vue2 基于 Object.defineProperty 方法重定义对象的 getter 与 setter。
这种方法并不能对诸如数组长度变化、增删元素操作、对象新增属性进行感知,在 vue 层面不得不重写一些数组方法(push、pop、unshift、shift 等),动态添加响应式属性,也要使用 $set 方法等。
关于Object.defineProperty() 的详细介绍可看这两篇文章,这里就不赘述了:《JavaScript中的Object.defineProperty()》《深入浅出Object.defineProperty()》
vue3 基于 Proxy 代理对象,拦截对象属性的访问与赋值过程。
经过proxy拦截的对象会返回所有的属性,包括之前定义的和新增的属性,这就解决了之前所无法监听的问题。
Proxy实现数据劫持:
observe(data) { const that = this; let handler = { get(target, property) { return target[property]; }, set(target, key, value) { let res = Reflect.set(target, key, value); that.subscribe[key].map(item => { item.update(); }); return res; } } this.$data = new Proxy(data, handler); }
Vue3.0 所采用的 Composition Api与 Vue2.x 使用的Options Api有什么不同?
composition API 可以说是 Vue3 的最大特点,通常使用 vue2 开发的项目,普遍会存在以下问题:
1、代码的可读性随着组件变大而变差
2、每一种代码复用的方式,都存在缺点
3、TypeScript 支持有限options API:
即大家常说的选项 API,即以 vue 为后缀的文件,通过定义methods,computed,watch,data 等属性与方法,共同处理页面逻辑。随着组件变得复杂,对应属性的列表也会增长,这可能会导致组件难以阅读和理解。
Composition API:
在 Vue3 Composition API 中,组件根据逻辑功能来分类的,一个功能所定义的所有 API 会放在一起(更加的高内聚,低耦合)
即使项目很大,功能很多,我们都能快速的定位到这个功能所用到的所有 API。
Vue3新增:
Vue3中的
Tree shaking
是什么?它的作用是什么?
答:Tree shaking
是一种通过清除多余代码方式来优化项目打包体积的技术,简单来讲,就是在保持代码运行结果不变的前提下,去除无用的代码。Vue3中的Teleport是什么?它的作用是什么?
答:Vue3中的Teleport 是控制渲染位置的新指令。它的作用是在DOM中移动一个组件的内容而不改变组件的父级。
Vue3中的Suspense是什么?它的作用是什么?
答:Vue3中的Suspense是Vue3中新增的一个组件,它的作用是实现延迟加载和错误处理。在组件中加入Suspense,可以让异步组件可以渲染出加载状态,并且如果异步组件加载时出现错误,也能够处理这些错误。
Vue3中的Fragment是什么?它的作用是什么?
答:Vue3中的Fragment是用来承载多个子元素的虚拟组件。它的作用是可以解决在Vue2中,使用v-for迭代元素时需要添加一个包装元素的问题。
Vue组件间通信
父子级通信推荐使用:props/$emit、$parent/$children/$refs、插槽slot、$attrs/$listeners
兄弟组件通信推荐使用:事件中心$emit/$on、Vuex/pinia
无关系组件通信推荐使用:$emit/$on、Vuex/pinia、$attrs/$listeners、provide/inject
想了解全部详细的组件通信,请点这里《Vue组件通信》
Vue Router的路由守卫
router.beforeEach、router.beforeResolve、router.afterEach......
路由守卫接受三个参数:
- to:route即将进入的目标路由对象,
- from:route当前导航正要离开的路由
- next:function一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。可以控制网页的跳转。
Vue Router的hash和history模式
对于vue这类渐进式前端开发框架,为了构建 SPA(单页面应用),需要引入前端路由系统,这也就是 Vue-Router 存在的意义。前端路由的核心,就在于 —— 改变视图的同时不会向后端发出请求。
为了达到这一目的,浏览器当前提供了以下两种支持:
hash —— 即地址栏 URL 中的 # 符号(此 hash 不是密码学里的散列运算)。比如这个 URL:http://www.abc.com/#/hello hash 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
history —— 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会e向后端发送请求。
Vuex有五个核心概念:
state
, getters
, mutations
, actions
, modules
。
1. state:vuex的基本数据,用来存储变量
2. geeter:从基本数据(state)派生的数据,相当于state的计算属性
3. mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。
4. action:和mutation的功能大致相同,不同之处在于:1. Action 提交的是 mutation,而不是直接变更状态。 2. Action 可以包含任意异步操作。
5. modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
keep-alive的作用是什么?
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件缓存下来保留状态,避免重新渲染。两个钩子:activated 和 deactivated,钩子会在 <keep-alive> 树内的所有嵌套组件中触发。
常用应用场景有:
- 商品列表页点击商品跳转到商品详情,返回后仍显示原有信息
- 订单列表跳转到订单详情,返回,等等场景。
keep-alive的生命周期
- 初次进入时:created > mounted > activated;退出后触发 deactivated
- 再次进入:会触发 activated;事件挂载的方法等,只执行一次的放在 mounted 中;组件每次进去执行的方法放在 activated 中
有关keep-alive->《利用Vue中keep-alive,快速实现页面缓存》
react和vue的异同:
- 模板写法,Vue的模板写法接近标准HTML,只是多了一些属性;React的模板使用JSX书写,写法是原生JS。
- 监听数据变化的实现原理不同,vue 双向数据流,数据可变;React 单向响应数据流,强调数据的不可变。
- 在 Vue 中我们组合不同功能的方式是通过 mixin,而在React中我们通过 HoC (高阶组件)。
- 组件通信:父组件都可以通过 props 向子组件传递数据或者回调;子组件向父组件传值,Vue有事件和回调两种,一般更倾向于使用事件,但是在 React 中都是使用回调函数的。
- 使用typescript,react比vue更合适。