2023 面试题vue2、vue3篇(持续更新)

vue的两个核心

  1. 数据驱动
  2. 组件系统

什么是虚拟dom

简单描述:虚拟 DOM(Virtual DOM)是一种轻量级的 JavaScript 对象,它描述了真实 DOM 中的节点信息和属性。虚拟 DOM 可以在内存中进行操作,然后通过算法比较新旧虚拟 DOM 的差异,最终只对发生变化的部分进行 DOM 操作,从而提高了性能。

什么是diff算法

diff的过程就是调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁

Vue 响应式原理

响应式原理3个步骤:数据劫持、依赖收集、派发更新。
1、从 new Vue 开始,首先通过 get、set 监听 Data 中的数据变化,同时创建 Dep 用来搜集使用该 Data 的 Watcher。
2、编译模板,创建 Watcher,并将 Dep.target 标识为当前 Watcher。
3、编译模板时,如果使用到了 Data 中的数据,就会触发 Data 的 get 方法,然后调用 Dep.addSub 将 Watcher 搜集起来。
4、数据更新时,会触发 Data 的 set 方法,然后调用 Dep.notify 通知所有使用到该 Data 的 Watcher 去更新 DOM。

vue双向绑定(v-model )的原理?

我们在 vue 项目中主要使用 v-model 指令在表单 input、textarea、select 等元素上创建双向数据绑定,我们知道 v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:

  • text 和 textarea 元素使用 value 属性和 input 事件;
  • checkbox 和 radio 使用 checked 属性和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。
    如果在自定义组件中,v-model 默认会利用名为 value 的 prop 和名为 input 的事件

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

对象在栈中存储的都是地址,函数的作用就是属性私有化,保证组件修改自身属性时不会影响其他复用组件。

data用return返回

不使用return包裹的数据会在项目的全局可见,会造成变量污染;使用return包裹后数据中变量只在当前组件中生效,不会影响其他组件。

$nextTick 原理及作用

Vue 的 nextTick 其本质是对 JavaScript 执行原理 EventLoop 的一种应用。
nextTick 的核心是利用了如 Promise 、MutationObserver、setImmediate、setTimeout的原生 JavaScript 方法来模拟对应的微/宏任务的实现,本质是为了利用 JavaScript 的这些异步回调任务队列来实现 Vue 框架中自己的异步回调队列。

什么是单向数据流

单向数据流指只能从一个方向来修改状态
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
简单来说就是:子组件无法更改prop,只能通知父组件从而改变传递过来的prop。

子组件prop接收数据之后刷新页面,数据丢失怎么处理?

1、通过后台来保存数据。
2、本地持久化。
3、通过vuex持久化。
4、通过url传递参数,保存在url中。

vue2和vue3的区别

API模式不同

Vue2与Vue3 最大的区别:Vue2使用选项式API(Options API)对比Vue3组合式API(Composition API)

监测机制的改变

vue3 中使用了ES6 的 ProxyAPI 对数据代理,监测的是整个对象,而不再是某个属性。

  • 消除了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限制
  • vue3可以监测到对象属性的添加和删除,可以监听数组的变化;
  • vue3支持 Map、Set、WeakMap 和 WeakSet。

建立数据的方式不同

  • Vue2:这里把数据放入data属性中
  • Vue3:需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。

生命周期钩子不同

基本上就是在 Vue2 生命周期钩子函数名基础上加了 on;beforeDestory 和 destoryed 更名为 onBeforeUnmount 和 onUnmounted;然后用setup代替了两个钩子函数 beforeCreate 和 created;新增了两个开发环境用于调试的钩子

  • setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method
  • onBeforeMount() : 组件挂载到节点上之前执行的函数。
  • onMounted() : 组件挂载完成后执行的函数。
  • onBeforeUpdate(): 组件更新之前执行的函数。
  • onUpdated(): 组件更新完成之后执行的函数。
  • onBeforeUnmount(): 组件卸载之前执行的函数
  • onUnmounted(): 组件卸载完成后执行的函数

若组件被包含,则多出下面两个钩子函

  • onActivated(): 被包含在中的组件,会多出两个生命周期钩子函数。被激活时执行 。
  • onDeactivated(): 比如从 A组件,切换到 B 组件,A 组件消失时执行。

父子传参不同

子组件通过defineProps()进行接收,并且接收这个函数的返回值进行数据操作。
总结: vue3 性能更高, 体积更小, 更利于复用, 代码维护更方便

defineProperty和proxy的区别

Vue 在实例初始化时遍历 data 中的所有属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。并 劫持各个属性 getter 和 setter,在数据变化时发布消息给订阅者,触发相应的监听回调,而这之间存在几个问题

  • 初始化时需要遍历对象所有 key,如果对象层次较深,性能不好
  • 通知更新过程需要维护大量 dep 实例和 watcher 实例,额外占用内存较多
  • Object.defineProperty 无法监听到数组元素的变化,只能通过劫持重写数方法
  • 动态新增,删除对象属性无法拦截,只能用特定 set/delete API 代替
  • 不支持 Map、Set 等数据结构

Vue3 使用 Proxy 来监控数据的变化。Proxy 是 ES6 中提供的功能,其作用为:用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。相对于Object.defineProperty(),其有以下特点:

  • Proxy 直接代理整个对象而非对象属性,这样只需做一层代理就可以监听同级结构下的所有属性变化,包括新增属性和删除属性。
  • 它的处理方式是在 getter 中去递归响应式,这样的好处是真正访问到的内部属性才会变成响应式,简单的可以说是按需实现响应式,减少性能消耗。
  • Proxy 可以监听数组的变化。

Vue3 Diff算法和 Vue2 的区别

我们知道在数据变更触发页面重新渲染,会生成虚拟 DOM 并进行 patch 过程,这一过程在 Vue3 中的优化有如下

编译阶段的优化:

  • 事件缓存:将事件缓存(如: @click),可以理解为变成静态的了
  • 静态提升:第一次创建静态节点时保存,后续直接复用
  • 添加静态标记:给节点添加静态标记,以优化 Diff 过程
    由于编译阶段的优化,除了能更快的生成虚拟 DOM 以外,还使得 Diff 时可以跳过"永远不会变化的节点",

Diff 优化如下

  • Vue2 是全量 Diff,Vue3 是静态标记 + 非全量 Diff
  • 使用最长递增子序列优化了对比流程

composition API 与 options API的区别

vue2 采用的就是 optionsAPI

  • 优点:易于学习和使用, 每个代码有着明确的位置 (例如: 数据放 data 中, 方法放 methods中)
  • 缺点: 相似的逻辑, 不容易复用, 在大项目中尤为明显
  • 虽然 optionsAPI 可以通过mixins 提取相同的逻辑, 但是也并不是特别好维护

vue3 新增的就是 compositionAPI

  • compositionAPI 是基于 逻辑功能 组织代码的, 一个功能 api 相关放到一起
  • 即使项目大了, 功能多了, 也能快速定位功能相关的 api
  • 大大的提升了 代码可读性 和 可维护性

vue3 推荐使用 composition API, 也保留了options API

即就算不用composition API, 用 vue2 的写法也完全兼容!!

setup 函数

setup() 函数是 vue3 中,专门为组件提供的新属性。它为我们使用 vue3的 Composition API 新特性提供了统一的入口, setup 函数会在 beforeCreate 、created 之前执行, vue3也是取消了这两个钩子,统一用setup代替, 该函数相当于一个生命周期函数,vue中过去的data,methods,watch等全部都用对应的新增api写在setup()函数中。

setup() 接收两个参数 props 和 context。它里面不能使用 this,而是通过 context 对象来代替当前执行上下文绑定的对象,context 对象有四个属性:attrs、slots、emit、expose

Computed 和 Watch 的区别

  • computed 计算属性 : 依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值。
  • watch 侦听器 : 更多的是观察的作用,无缓存性,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。

watch 和 watchEffect 的区别

watch 作用是对传入的某个或多个值的变化进行监听;触发时会返回新值和老值;也就是说第一次不会执行,只有变化时才会重新执行。
watchEffect 是传入一个函数,会立即执行,所以默认第一次也会执行一次;不需要传入监听内容,会自动收集函数内的数据源作为依赖,在依赖变化的时候又会重新执行该函数,如果没有依赖就不会执行;而且不会返回变化前后的新值和老值。
共同点是 watch 和 watchEffect 会共享以下四种行为:

  • 停止监听:组件卸载时都会自动停止监听
  • 清除副作用:onInvalidate 会作为回调的第三个参数传入
  • 副作用刷新时机:响应式系统会缓存副作用函数,并异步刷新,避免同一个 tick 中多个状态改变导致的重复调用
  • 监听器调试:开发模式下可以用 onTrack 和 onTrigger 进行调试

vue的跳转有几种

vue的跳转共分为6种
1、标签跳转 router-link
2、事件跳转 this.$router.push()

描述:跳转到不同的url,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面。

3、this.$router.replace{path:‘/user’}

描述:同样是跳转到指定的url,但是这个方法不会向history里面添加新的记录,点击返回,会跳转到上上一个页面。上一个记录是不存在的。

4、this.$router.go(n)

描述:相对于当前页面向前或向后跳转多少个页面,类似 window.history.go(n)。n可为正数可为负数。正数返回上一个页面。

5、this.router.forward() 前进一步
6、this.router.back() 回退一步

vue的跳转传参有什么区别

query传参:
  1.可以使用name ,path , 字符串拼接方式传参
  2.每次刷新不会丢失数据
  3.不能使用props接收数据
 params传参:
  1.路由中不写占位符,只能使用name 传参
  2.不使用占位符,刷新会丢失数据,使用占位符则不丢失数据 所以需要在规则中配置属性名
  3.可以使用props接收数据
  
  (扩展:params防止数据丢失)
  在跳转到达的页面路由上这样写:

 {
      path: "/ordernoted/:id",//添加上要传递的参数
      name: "ordernoted",
      component: () => import("./views/ICK/Listpage/Ordernoted"),
      meta: {
        keepAlive: true
      }
    }

然后传参还是跟上面一样的方法传:

 this.$router.push({
        name:'ordernoted',
        params:{
          id:e.username
        }
      })

在下个页面接收:

 var items =this.$route.params.id
    console.log(items)

多个参数的话可以这样写:

path: "/ordernoted/:jum/:id",//可以一直在后边拼接参数

route和router的区别

route是路由信息对象,每一个路由都会有一个route对象,是一个局部的对象,里面主要包含路由的一些基本信息
如:$route.name 当前路径名字、 r o u t e . m e t a 路由元信息、 route.meta 路由元信息、 route.meta路由元信息、route.path 字符串,对应当前路由的路径,总是解析为绝对路径
router是VueRouter的实例,通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了许多关键的对象和属性
如: r o u t e r . g o ( ) 、 router.go()、 router.go()router.push()

谈谈你对 keep-alive 的了解?

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

  • 一般结合路由和动态组件一起使用,用于缓存组件;
  • 提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;
  • 对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。

slot是什么?有什么作用?原理是什么?

slot又名插槽,通过插槽可以动态指定某一个组件模板部分的渲染, 我们在调用组件的时候, 在组件的调用标签中间传递了什么样的标签结构, 那么该组件就会把我们传递的标签结构放在他的模板部分进行渲染.。slot又分三类,默认插槽,具名插槽和作用域插槽。

  • 默认插槽:又名匿名插槽,当slot没有指定name属性值的时候一个默认显示插槽,一个组件内只有有一个匿名插槽。
  • 具名插槽:带有具体名字的插槽,也就是带有name属性的slot,一个组件可以出现多个具名插槽。
  • 作用域插槽:默认插槽、具名插槽的一个变体,可以是匿名插槽,也可以是具名插槽,该插槽的不同点是在子组件渲染作用域插槽时,可以将子组件内部的数据传递给父组件,让父组件根据子组件的传递过来的数据决定如何渲染该插槽。
    实现原理: 当子组件vm实例化时,获取到父组件传入的slot标签的内容,存放在vm. s l o t 中,默认插槽为 v m . slot中,默认插槽为vm. slot中,默认插槽为vm.slot.default,具名插槽为vm. s l o t . x x x , x x x 为插槽名,当组件执行渲染函数时候,遇到 s l o t 标签,使用 slot.xxx,xxx 为插槽名,当组件执行渲染函数时候,遇到slot标签,使用 slot.xxxxxx为插槽名,当组件执行渲染函数时候,遇到slot标签,使用slot中的内容进行替换,此时可以为插槽传递数据,若存在数据,则可称该插槽为作用域插槽。

vue-router 路由模式有几种?

hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器;
history: 它使用的是传统的路由分发模式,即用户在输入一个URL时,服务器会接收这个请求,并解析这个URL,然后做出相应的逻辑处理。
**abstract :**支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式.

Vue-router 路由钩子

1、全局路由钩子
vue-router全局有三个路由钩子;

  • router.beforeEach 全局前置守卫 进入路由之前
  • router.beforeResolve 全局解析守卫(2.5.0+)在 beforeRouteEnter 调用之后调用
  • router.afterEach 全局后置钩子 进入路由之后
    2、单个路由独享钩子
    如果不想全局配置守卫的话,可以为某些路由单独配置守卫,有三个参数∶ to、from、next
    3、组件内钩子
  • beforeRouteEnter∶ 进入组件前触发
  • beforeRouteUpdate∶ 当前地址改变并且改组件被复用时触发,举例来说,带有动态参数的路径foo/∶id,在 /foo/1 和 /foo/2 之间跳转的时候,由于会渲染同样的foa组件,这个钩子在这种情况下就会被调用
  • beforeRouteLeave∶ 离开组件被调用

什么是Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
(1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
(2)改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。

vuex有哪几种属性?

有五种,分别是 State、 Getter、Mutation 、Action、 Module

state:存放公共数据的地方;

getter:获取根据业务场景处理返回的数据;

mutations:唯一修改state的方法,修改过程是同步的;

action:异步处理,通过分发操作触发mutation;

module:将store模块分割,模块化,命名空间;

在组件中怎么访问Vuex模块中的getter和state,怎么提交mutation和action?

直接通过this.$store.getters和this.$store.state来访问模块中的getter和state。
直接通过this.$store.commit('mutationA',data)提交模块中的mutation。
直接通过this.$store.dispatch('actionA,data')提交模块中的action。

Vuex中action和mutation有什么区别?

  • Mutation专注于修改State,理论上是修改State的唯一途径;Action业务代码、异步请求。
  • Mutation:必须同步执行;Action:可以异步,但不能直接操作State。
  • 在视图更新时,先触发actions,actions再触发mutation

Vue 有哪些常用的事件修饰符?

.prevent: 阻止默认事件;
.stop: 阻止冒泡;
.once: 事件执行一次;
.self: 只当在 event.target 是当前元素自身时触发处理函数

对SSR的理解

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

SSR的优势:

  • 更好的SEO
  • 首屏加载速度更快
    SSR的缺点:
  • 开发条件会受到限制,服务器端渲染只支持beforeCreate和created两个钩子;
  • 当需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于Node.js的运行环境;
  • 更多的服务端负载。

vue如何获取dom,在哪个生命周期里面可以获取?

1、使用DOM API直接找元素
Vue组件在patch阶段结束时会把this. e l 赋值为挂载的根 d o m 元素,我们可以直接使用 el赋值为挂载的根dom元素,我们可以直接使用 el赋值为挂载的根dom元素,我们可以直接使用el的querySelector, querySelectorAll等方法获取匹配的元素。
2、refs
使用组件实例的$refs即可拿到组件上ref属性对应的元素。
如果ref属性加在一个组件上,那么拿到的是这个组件的实例,否则拿到的就是dom元素了。
3、使用自定义指令
mounted()时才能获取

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值