vue3面试题:2024 最新前端 Vue 3

12,324次阅读
没有评论

共计 6680 个字符,预计需要花费 17 分钟才能阅读完成。

+ 父组件中绑定事件

 
```

```
+ 子组件中声明自定义事件

 
```

```
  • 移除 过滤器(filter)

过滤器虽然这看起来很方便,但它需要一个自定义语法,打破大括号内表达式是“只是 JavaScript”的假设,这不仅有学习成本,而且有实现成本!建议用方法调用或计算属性去替换过滤器。

3、生命周期(vue2 和 vue3 的生命周期对比)有哪些?

vue2.x 的生命周期

vue3.0 的生命周期

1

  • Vue3.0 中可以继续使用 Vue2.x 中的生命周期钩子,但有有两个被更名:

    • beforeDestroy改名为 beforeUnmount
    • destroyed改名为 unmounted
  • Vue3.0 也提供了 Composition API 形式的生命周期钩子,与 Vue2.x 中钩子对应关系如下:

    • beforeCreate===>setup()
    • created=======>setup()
    • beforeMount ===>onBeforeMount
    • mounted=======>onMounted
    • beforeUpdate===>onBeforeUpdate
    • updated =======>onUpdated
    • beforeUnmount ==>onBeforeUnmount
    • unmounted =====>onUnmounted

4、Vue3.0 中的响应式原理是什么?vue2 的响应式原理是什么?

vue2.x 的响应式
  • 实现原理:

    • 对象类型:通过 Object.defineProperty() 对属性的读取、修改进行拦截(数据劫持)。
    • 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)。
    Object.defineProperty(data, 'count', {get () {}, 
        set () {}
    })
    
  • 存在问题:

    • 新增属性、删除属性, 界面不会更新。
    • 直接通过下标修改数组, 界面不会自动更新。
Vue3.0 的响应式
  • 实现原理:

    • 通过 Proxy(代理): 拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。

    • 通过 Reflect(反射): 对源对象的属性进行操作。

    • MDN 文档中描述的 Proxy 与 Reflect:

      • Proxy:Proxy – JavaScript | MDN
      • Reflect:Reflect – JavaScript | MDN
      new Proxy(data, {
          // 拦截读取属性值
          get (target, prop) {return Reflect.get(target, prop)
          },
          // 拦截设置属性值或添加新属性
          set (target, prop, value) {return Reflect.set(target, prop, value)
          },
          // 拦截删除属性
          deleteProperty (target, prop) {return Reflect.deleteProperty(target, prop)
          }
      })
      ​
      proxy.name = 'tom'   
      

5、vue3 响应式数据的判断?

  • isRef: 检查一个值是否为一个 ref 对象
  • isReactive: 检查一个对象是否是由 reactive 创建的响应式代理
  • isReadonly: 检查一个对象是否是由 readonly 创建的只读代理
  • isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理

6、vue3 的常用 Composition API 有哪些?

官方文档: 介绍 | Vue.js

1. 拉开序幕的 setup

  1. 理解:Vue3.0 中一个新的配置项,值为一个函数。

  2. setup 是所有Composition API(组合 API)“表演的舞台”

  3. 组件中所用到的:数据、方法等等,均要配置在 setup 中。

  4. setup 函数的两种返回值:

    1. 若返回一个对象,则对象中的属性、方法, 在模板中均可以直接使用。(重点关注!)
    2. 若返回一个渲染函数:则可以自定义渲染内容。(了解)

5.setup 的几个注意点

  • setup 执行的时机

    • 在 beforeCreate 之前执行一次,this 是 undefined。
  • setup 的参数

    • props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。

    • context:上下文对象

      • attrs: 值为对象,包含:组件外部传递过来,但没有在 props 配置中声明的属性, 相当于 this.$attrs
      • slots: 收到的插槽内容, 相当于 this.$slots
      • emit: 分发自定义事件的函数, 相当于 this.$emit
  • 尽量不要与 Vue2.x 配置混用

    • Vue2.x 配置(data、methos、computed…)中 可以访问到setup 中的属性、方法。
    • 但在 setup 中 不能访问到Vue2.x 配置(data、methos、computed…)。
    • 如果有重名, setup 优先。
  • setup 不能是一个 async 函数,因为返回值不再是 return 的对象, 而是 promise, 模板看不到 return 对象中的属性。(后期也可以返回一个 Promise 实例,但需要 Suspense 和异步组件的配合)

2.ref 函数

3.reactive 函数

  • 作用: 定义一个 对象类型 的响应式数据(基本类型不要用它,要用 ref 函数)
  • 语法:const 代理对象 = reactive(源对象)接收一个对象(或数组),返回一个 代理对象(Proxy 的实例对象,简称 proxy 对象)
  • reactive 定义的响应式数据是“深层次的”。
  • 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。

4.reactive 对比 ref

5. 计算属性与监视

1.computed 函数
  • 与 Vue2.x 中 computed 配置功能一致
  • 写法
import {computed} from 'vue'
​
setup(){
    ...
    // 计算属性——简写
    let fullName = computed(()=>{return person.firstName + '-' + person.lastName})
    // 计算属性——完整
    let fullName = computed({get(){return person.firstName + '-' + person.lastName},
        set(value){const nameArr = value.split('-')
            person.firstName = nameArr[0]
            person.lastName = nameArr[1]
        }
    })
}
2.watch 函数
// 情况一:监视 ref 定义的响应式数据
watch(sum,(newValue,oldValue)=>{console.log('sum 变化了',newValue,oldValue)
},{immediate:true})
​
// 情况二:监视多个 ref 定义的响应式数据
watch([sum,msg],(newValue,oldValue)=>{console.log('sum 或 msg 变化了',newValue,oldValue)
}) 
​
/* 情况三:监视 reactive 定义的响应式数据
            若 watch 监视的是 reactive 定义的响应式数据,则无法正确获得 oldValue!!若 watch 监视的是 reactive 定义的响应式数据,则强制开启了深度监视 
*/
watch(person,(newValue,oldValue)=>{console.log('person 变化了',newValue,oldValue)
},{immediate:true,deep:false}) // 此处的 deep 配置不再奏效
​
// 情况四:监视 reactive 定义的响应式数据中的某个属性
watch(()=>person.job,(newValue,oldValue)=>{console.log('person 的 job 变化了',newValue,oldValue)
},{immediate:true,deep:true}) 
​
// 情况五:监视 reactive 定义的响应式数据中的某些属性
watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{console.log('person 的 job 变化了',newValue,oldValue)
},{immediate:true,deep:true})
​
// 特殊情况
watch(()=>person.job,(newValue,oldValue)=>{console.log('person 的 job 变化了',newValue,oldValue)
},{deep:true}) // 此处由于监视的是 reactive 素定义的对象中的某个属性,所以 deep 配置有效
3.watchEffect 函数
  • watch 的套路是:既要指明监视的属性,也要指明监视的回调。

  • watchEffect 的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。

  • watchEffect 有点像 computed:

    • 但 computed 注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
    • 而 watchEffect 更注重的是过程(回调函数的函数体),所以不用写返回值。
//watchEffect 所指定的回调中用到的数据只要发生变化,则直接重新执行回调。watchEffect(()=>{
    const x1 = sum.value
    const x2 = person.age
    console.log('watchEffect 配置的回调执行了')
})

10.toRef

  • 作用:创建一个 ref 对象,其 value 值指向另一个对象中的某个属性。

  • 语法:const name = toRef(person,'name')

  • 应用: 要将响应式对象中的某个属性单独提供给外部使用时。

  • 扩展:toRefstoRef 功能一致,但可以批量创建多个 ref 对象,语法:toRefs(person)

1.shallowReactive 与 shallowRef

  • shallowReactive:只处理对象最外层属性的响应式(浅响应式)。

  • shallowRef:只处理基本数据类型的响应式, 不进行对象的响应式处理。

  • 什么时候使用?

    • 如果有一个对象数据,结构比较深, 但变化时只是外层属性变化 ===> shallowReactive。
    • 如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换 ===> shallowRef。

2.readonly 与 shallowReadonly

  • readonly: 让一个响应式数据变为只读的(深只读)。
  • shallowReadonly:让一个响应式数据变为只读的(浅只读)。
  • 应用场景: 不希望数据被修改时。

3.toRaw 与 markRaw

  • toRaw:

    • 作用:将一个由 reactive 生成的 响应式对象 转为 普通对象
    • 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。
  • markRaw:

4.customRef

  • 作用:创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。
  • 实现防抖效果:

5.provide 与 inject

  • 作用:实现 祖与后代组件间 通信

  • 套路:父组件有一个 provide 选项来提供数据,后代组件有一个 inject 选项来开始使用这些数据

  • 具体写法:

    1. 祖组件中:
    setup(){
        ......
        let car = reactive({name:'奔驰',price:'40 万'})
        provide('car',car)
        ......
    }
    
    1. 后代组件中:
    setup(props,context){
        ......
        const car = inject('car')
        return {car}
        ......
    }
    

7、vue3 为什么要添加新的组合 API,它可以解决哪些问题

在 Vue2.0 中,随着功能的增加,组件越来越复杂,维护起来也越来越难,而难以维护的根本原因是 Vue 的 API 设计迫使开发者使用监视、计算、方法 Option 组织代码,而不是实际的业务逻辑。

另外 Vue2.0 缺乏一个简单而低成本的机制来完成逻辑重用,虽然你可以 minxis 完全重用逻辑,但是当 mixin 更多的时候,就使得很难找到相应的数据,计算出来也许是从中 mixin 的方法,使得类型推断变得困难。

因此组合 API 外观,主要是解决选项 API 带来的问题,首先是代码组织,组合 API 开发者可以根据业务逻辑组织自己的代码,让代码更具可读性和可扩展性,也就是说,当下一个开发者接触到这段不是自己写的代码,他可以更好地利用代码的组织来反转实际的业务逻辑,或者根据业务逻辑更好地理解代码。

二是实现代码的逻辑提取和重用,当然 mixin 逻辑提取和重用也可以实现,但就像我之前说的,多个 mixin 在作用于同一个组件时,很难看出 mixin 的属性,来源不明确,另外,多个 mixin 的属性存在变量命名冲突的风险。而 Composition API 恰恰解决了这两个问题。

8、什么是 hook?什么是自定义 hook 函数?

  • 什么是 hook?—— 本质是一个函数,把 setup 函数中使用的 Composition API 进行了封装。
  • 类似于 vue2.x 中的 mixin。
  • 自定义 hook 的优势: 复用代码, 让 setup 中的逻辑更清楚易懂。

9、都说 Composition API 和 React Hook 很像,请问他们的区别是什么?

从 React Hook 从实现的角度来看,React Hook 是基于 useState 的调用顺序来确定下一个 re 渲染时间状态从哪个 useState 开始,所以有以下几个限制

  • 不在循环中、条件、调用嵌套函数 Hook
  • 你必须确保它总是在你这边 React Top level 调用函数 Hook
  • 使用效果、使用备忘录 依赖关系必须手动确定

和 Composition API 是基于 Vue 的响应系统,和 React Hook 相比

  • 在设置函数中,一个组件实例只调用一次设置,而 React Hook 每次重新渲染时,都需要调用 Hook,给 React 带来的 GC 比 Vue 更大的压力,性能也相对 Vue 对我来说也比较慢
  • Compositon API 你不必担心调用的顺序,它也可以在循环中、条件、在嵌套函数中使用
  • 响应式系统自动实现依赖关系收集,而且组件的性能优化是由 Vue 内部完成的,而 React Hook 的依赖关系需要手动传递,并且依赖关系的顺序必须得到保证,让路 useEffect、useMemo 等等,否则组件性能会因为依赖关系不正确而下降。

虽然 Compoliton API 看起来像 React Hook 来使用,但它的设计思路也是 React Hook 的参考。

10、Options API 存在的问题是什么?Composition API 的优势有哪些?

1.Options API 存在的问题

使用传统 OptionsAPI 中,新增或者修改一个需求,就需要分别在 data,methods,computed 里修改。

打开全栈工匠技能包 - 1 小时轻松掌握 SSR

两小时精通 jq+bs 插件开发

生产环境下如歌部署 Node.js

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

网易内部 VUE 自定义插件库 NPM 集成

谁说前端不用懂安全,XSS 跨站脚本的危害

webpack 的 loader 到底是什么样的?两小时带你写一个自己 loader

原文地址: vue3 面试题:2024 最新前端 Vue 3

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-10-29发表,共计6680字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)