vue3.0面试题整理

1.Vue3 比 vue2 优势

1. 性能更好
2. 体积更小
3. 更好的ts支持
4. 更好的代码组织
5. 更好的逻辑抽离
6. 更多新的功能

2.Vue3 升级了哪些重要的功能?

1. createApp:创建vue实例的方式
2. emits属性,组件中的事件要先使用emits进行声明,然后在setup的形参引入
3. 生命周期
4. 多事件
5. fragment:不再限制唯一根节点
6. 移除.sync:
7. 异步组件的写法:Vue2 直接import进来,Vue3需要使用defineAsyncComponent包裹一层
8. 移除filter
9. teleport:把组件直接to到某个dom
10. suspense:fallback,就是一个具名插槽
11. composition API

3.Vue3 生命周期

1. Options API生命周期
	
2. Composition  API生命周期

4.如何看待composition API 和options API

1. Composition API 更好的代码组织,更好的逻辑复用,更好的类型推到
2. 小型项目,业务逻辑简单,用Options API
3. 中大型项目,业务逻辑复杂的,用Composition API
4. Composition API 是为了解决复杂业务逻辑而设计的
5. 类似React Hooks

5.如何理解ref toRef和toRefs?

1. ref
    1. 生成值类型的响应式数据
    2. 可用于模板和reactive
    3. 通过.value修改值
2. toRef
    1. 针对一个响应式对象(reactive封装)的prop
    2. 创建一个ref,具有响应式
    3. 两者保持引用关系
3. toRefs,避免模板中导出都是state
    1. 将响应式对象(reactive封装)转换成普通对象
    2. 对象的每个prop都是对应的ref
    3. 两者保持引用关系
4. 最佳使用方式
    1. 用reactive做对象的响应式,用ref做值类型的响应式
    2. setup中返回toRefs(state),或者toRef(state, 'prop')
    3. ref的变量命名都用xxxRef
    4. 合成函数返回响应式对象时,用toRefs

6.ref toRef toRefs进阶,深入理解

1. 为何需要ref?
    1. 返回值类型,会丢失响应式
    2. setup、computed、合成函数,都有可能返回值类型
    3. Vue如果不定义ref,用户将自定义ref,反而混乱
2. 为何需要.value?
    1. ref是一个对象(不丢失响应式),value存储值
    2. 通过.value属性的get和set实现响应式
    3. 用于模板、reactive时,不需要.value,其他情况都需要
3. 为何需要toRef toRefs
    1. 初衷:不丢失响应式的情况下,把对象数据进行分解和扩散
    2. 前提:针对的事响应式对象,不是普通对象
    3. 注意:不创造响应式,而是延续响应式

7.Composition API如何实现代码逻辑复用?

1. 抽离逻辑代码到一个函数
2. 函数命名约定为useXXX格式(React Hooks也是)
3. 在setup中引用useXXX函数

8.Reflect作用

1. 与proxy能力对应
2. 规范化,标准化,函数式
3. 替代Object上的工具函数

9.watch和watchEffect的区别是什么?

1. 二者都可以监听属性变化
2. watch需要明确监听哪个属性
3. watchEffect会根据其中的属性,自动监听其变化

10.setup中如何获取组件实例?

1. setup和其他Composition API中都没有this
2. 在Options API中仍然可以使用this
3. Composition API中可以使用getCurrentInstance方法获取

11.Vite是什么?

1. 前端打包工具
2. 在开发环境下,使用ES6 Module,不打包,启动快
3. 生产环境打包使用rollup

12.Composition API和React Hooks的对比

1. 前者setup(生命周期create)只会被调用一次,后者函数会被多次调用
2. 前者无需useMemo,useCallback,因为setup只调用一次
3. 前者无需考虑调用顺序,后者需要保证hooks的顺序一致
4. 前者reactive + ref 比后者的useState,要难理解

13.Vue3为何比Vue2快?

1. Proxy实现响应式
2. patchFlag https://vue-next-template-explorer.netlify.app/
    1. 编译模板时,动态节点做标记
    2. 标记,分为不同的类型,如TEXT,PROPS
    3. diff时,区分静态节点和不同类型的动态节点
3. hoistStatic
    1. 将静态节点的定义,提升到父作用域,缓存起来,空间换时间
    2. 多个相邻的静态节点,会被合并起来,编译优化
4. cacheHandler
    缓存事件
5. SSR优化
    静态节点直接输出为dom,绕过vdom
6. tree-shaking
    编译时,按需引入API

14.vue3为什么要用proxy实现双向绑定?

object.defineProperty的缺点:

1.因为es5的object.defineProperty无法监听对象属性的删除和添加
2.不能监听数组的变化,除了push/pop/shift/unshift/splice/spObject.definert/reverse,其他都不行
3.Object.defineProperty只能遍历对象属性直接修改(需要深拷贝进行修改)

proxy的优点:

1.直接监听对象而非属性
2.直接监听数组的变化
3.拦截的方式有很多种(有13种,set,get,has)
4.Proxy返回一个新对象,可以操作新对象达到目的

proxy的缺点:

proxy有兼容性问题,不能用polyfill来兼容(polyfill主要抚平不同浏览器之间对js实现的差异)

实现Vue3双向绑定

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div></div>
    <script>
        const toProxy = new WeakMap(); //存放的是代理后的对象
        const toRaw = new WeakMap();   //存放的是代理前的对象
        function trigger() {
            console.log('触发视图更新')
        }
        function isObject(target) {
            return typeof target === 'object' && target !== null;
        }
        function reactive(target) {
            if (!isObject(target)) {
                return target;
            }
            let proxy = toProxy.get(target)
            // 如果代理表中已经存在了  就把这个结果返回
            if (proxy) {
                return proxy
            }
            // 如果这个对象已经被代理过了  就直接返回
            if (toRaw.has(target)) {
                return target;
            }
            const handlers = {
                set(target, key, value, receiver) {
                    if (target.hasOwnProperty(key)) {
                        trigger()

                    }
                    return Reflect.set(target, key, value, receiver)
                },
                get(target, key, value, receiver) {
                    const res = Reflect.get(target, key, receiver)
                    if (isObject(target[key])) {
                        return reactive(res)
                    }
                    return res;
                },
                deleteProperty(target, key) {
                    return Reflect.deleteProperty(target, key)
                }
            }
            let observed = new Proxy(target, handlers)
            toProxy.set(target, observed);
            toRaw.set(observed, target)
            return observed
        }
        let obj = {
            name: '温小鹿',
            arr: [1, 2, 3]
        }
        // let p = reactive(obj)
        // p.name = 'jw'
        // let arr = [1, 2 ,3];
        // let p = reactive(arr)
        // p.push(4);
        // console.log(p)

        let p = reactive(obj)
        p = reactive(p)
        p = reactive(p)
        p.arr.push(4)
        console.log(p)
    </script>
</body>
</html>

Reflect是ES6为操作对象而提供的新API,proxy对象的方法在rReflect上都能找到
new WeakMap() 是弱引用,在内存不足的时候垃圾回收机制才会回收,可以作为缓存

15.Object.defineProperty 和 Proxy 的区别

Object.defineProperty 和 Proxy 的区别如下:

1.Proxy 可以直接监听对象而非属性;
2.Proxy 可以直接监听数组的变化;
3.Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的
4.Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty 只能遍历对象属性直接修改
5.Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利
6.Object.defineProperty 兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平,因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写

16.怎么在 watch 监听开始之后立即被调用?
在选项参数中指定 immediate: true 将立即以表达式的当前值触发回调

17. 为什么vue3需要对引入的组件使用markRaw?
vue2中 is是通过组件名称切换的,vue3中setup是通过组件实例切换的。直接把组件实例放到reactive中代理,vue会发出警告。告知我们可以通过shallowRef 或者 markRaw 跳过proxy 代理。对组件实例进行响应式代理毫无意义,且浪费性能

markRaw:标记一个对象,使其不能成为一个响应式对象。
toRaw:将响应式对象(由 reactive定义的响应式)转换为普通对象。
shallowRef:只处理基本数据类型的响应式, 不进行对象的响应式处理。
shallowReactive:只处理对象最外层属性的响应式(浅响应式)。

<template>
	<component :is="currentComponent"></component>
</template>

<script setup>
import A from '../components/A.vue'
import B from '../components/B.vue'
let tabList = reactive([
	{name:'组件A',com:markRaw(A)},
	{name:'组件B',com:markRaw(B)},
]);

  • 12
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值