vue2与vue3面试题之区别

vue2与vue3面试题之区别

01:数据双向绑定( new proxy() 替代 object.defineProperty() )

  • Vue3对响应式模块进行了重写,主要修改就是proxy替换了defineProperty实现响应式。
  • Vue2使用defineProperty存在一些原因:
    • 对数组拦截有问题,需要做特殊处理
    • 不能拦截新增、删除的属性
    • defineProperty方案在初始化时候,需要深度递归遍历待处理的对象才能对它进行完全拦截,明显增加了初始化的时间。
  • Proxy代理
    • 对数组进行拦截,还能对Map,Set实现拦截
    • proxy是懒处理行为,没有嵌套对象时,不会实施拦截,也使之初始化速度和内存得到改善
    • proxy存在兼容性问题,IE不支持。
  • proxy属性拦截原理
function reactive( obj ) {
	return new Proxy ( obj, {
		get(target,key){},
		set(target,key,val) {},
		deleteProperty(target,key){}
	}
}

01-1 vue3双向绑定优点与vue2双向绑定的缺点

001: 在vue2之中,假如设置了obj:{a:1} 若是给obj对象添加一个b属性值,直接在methods之中使用方法 obj.b = 2,导致的问题是:数据有更新,但是视图没有更新( 需要使用this.$set()方法去设置b属性为响应式属性值,才能支持试图更新 );vue3之中直接使用reactive定义对象,则当前对象为响应式对象,对于obj.b = 2 视图会更新!

002: object.defineProperty对于后期添加的属性值是不参与劫持设置为响应式属性的,这就是为什么上面obj.b没有更新视图的缘故
002new Proxy对于后期添加的属性值是依旧走proxy内的setget,这就是obj.b更新视图的缘故
	
01-002-code vue2与vue3 设置响应式demo
// vue2 设置响应式属性demo
    let obj = {
      a: 1,
      b: 2
    }
    let vue = {}
    for (let k in obj) {
      Object.defineProperty(vue, k, {
        get() {
          console.log('获取了')
          return obj[k]
        },
        set(value) {
          obj[k] = value
        }
      })
    }
    console.log('obj', obj) // obj {a: 1, b: 2}
    vue.c = '000'
    console.log('vue-c', vue.c) // vue-c 000 没有走 Object.defineProperty这个逻辑
    console.log('vue-a', vue.a) // 获取了 vue-a 1 打印了,由于有a属性,则走了Object.defineProperty这个逻辑

// vue3 设置响应式属性demo
    let obj = {
      a: 1,
      b: 2
    }
    let vue = {}
    vue = new Proxy(obj, {
      get(target, key, receiver) {
        console.log('获取了')
        return Reflect.get(target, key, receiver)
      },
      set(target, key, val, receiver) {
        console.log('设置了')
        return Reflect.set(target, key, val, receiver)
      },
      deleteProperty(target, key) {}
    })

    vue.c = '000'
    console.log('vue-c', vue.c) // vue-c 000 设置了 获取了 vue3之中走了new Proxy的逻辑,设置为了响应式数据

02:生命周期函数的更换

  • vue2生命周期函数
    • beforeCreate、created 、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
  • vue3生命周期函数
    • setup 、onBeforeMount 、 onMounted 、onBeforeUpdate 、onUpdated 、onBeforeUnmount、onUnmounted

03:vue3的新特性

  • 1:Composition API 组合api

  • 2:Teleport 传送组件,把dom节点挂载到body等其他标签上

  • 3:Fragments 碎片化节点 ( 不需要根节点 )

  • 4:Emits Component Option自定义事件

  • 5:createRenderer 渲染器

  • 6:SFC State-driven CSS Variables (v-bind in style)

  • 7:SFC style scoped can now include global rules or rules that target only slotted content

  • 8:Suspense组件 异步组件

  • 再说说框架特性:

    • 更快:
      重写虚拟DOM(编译优化内容的存储、type属性支持更加多样)
      编译器优化:静态提升、patchFlags、block(区块)等
      基于Proxy的响应式系统(了解Vue3的响应式原理)
      更小:更好的摇树优化
      更容易维护:TypeScript + 模块化
      更容易扩展:
      独立的响应式模块
      自定义渲染器

04:缓存组件与更新组件

  • 使用keep-alive去缓存组件
    • include与exclude 包含和排除
      在这里插入图片描述
  • 更新组件
    • activated钩子函数之中进行更新
    • beforeRouterEnter

05:ref和reactive的区别

  • ref一般用于定义普通数据类型和dom节点,使用 .value去取值 ( toRefs 结构数据,变成响应式数据)
  • reactive一般用于定义复杂数据类型,使用的时候,直接取值即可
  • 源码上的区别
    • 1:ref若是定义的是简单数据类型,那么响应式原理走的是vue2的Object.defineProperty()的get与set方式,若是ref定义的是引用类型数据,那么响应式原理使用的proxy中Reflect.set与get
    • 2;reactive响应式原理直接使用的是proxy处理负责数据类型,内部使用了Reflect.get与set实现响应式的。

06:watch和watchEffect的区别

  • watch
    • 侦测一个或者多个响应式数据,并在数据源变化时再调用一个回调函数
  • watchEffect
    • 立即运行一个函数,被动地追踪它的依赖,当这些依赖改变时重新执行该函数

07:修改数组下标 不会影响视图

  • 数据是修改的,但是视图没有变化的
    • 原因:vue2是使用ObjectDefineProperty来实现的,只监听data数据存在的变量,对于循环添加新值的时候,监听不到,因此造成数据发生变化,视图没有发生变化
    • vue3 则不会有这样的问题,因为proxy会一直监听整个数据

08:定义数据的不一样

  • vue2 再data之中定义
  • vue3 则是再setup之中,使用ref、reactive等定义数据

09:父子传值的不一样

  • vue2 父传子,直接props,子传父,采用Emitting Events,this.$emit(‘事件’,参数)
  • vue3 父传子,直接props,子传父,采用Emitting Events,但需要从vue之中解构出defineEmits,再defineEmits(['事件名称‘])
    • const emit = defineEmits([“change-handerAdd”, “change-handerStep”]);
    • emit(“change-handerAdd”, id);

10:指令与插槽不同

  • 插槽
    • vue2 使用slot是直接使用slot的。
    • vue3 使用插槽必须为 v-slot
  • v-for与v-if指令
    • vue2的时候 v-for指令优先级比v-if高,先执行v-for再执行v-if,而且不推荐一起使用
    • vue3则再v-for之中使用的时候,把v-if当成一个判断语句,不会互相冲突的
  • vue移除了filter(过滤器)、也移除了keyCode作为v-on的修饰符、v-on.native修饰符

11 vue2和vue3响应式原理区别

vue3对于vue2来说,最大的变化就是composition Api 替换了vue2的options Api
vue3的响应式原理替换为了proxy,vue2的则是Object.defineproperty。其中proxy有着以下这些优点:
 - 1:对象新增的属性不需要使用$set添加响应式,因为proxy默认会监听动态添加属性和删除属性等操作
 - 2:消除数组上无法监听数组索引、length属性,不再进行数组原型对象上重写数组方法
 - 3:Object.defineproperty是劫持所有对象的属性设置为getter、setter,然后遍历递归去实现。而proxy则是代理了整个对象。
 - 4:vue2使用Object.defineproperty拦截对象的getset属性进行操作。而proxy有着13种拦截方法。
 - 5:由vue2的响应式原理可以看出,vue底层需要对vue实例的返回的每一个key进行getset操作,无论这个值有没有被用到。所以在vue中定义的data属性越多,那么初始化开销就会越大。而proxy是一个惰性的操作,它只会在用到这个key的时候才会执行get,改值的时候才会执行set。所以在vue3中实现响应式的性能实际上要比vue2实现响应式性能要好

+ proxy原理
 - 作用:能够为另外一个对象创建代理,该代理可以拦截和重新定义该对象的基本操作(获取,设置,定义属性等)
 - proxy的两个参数: 参数1=> 要代理的原始对象; 参数2=>一个对象,这个对象定义了操作将被拦截以及如何重新定义被拦截的操作
``js
const target = {name: "ts",age: 18};
const handler = {};
const proxy = new Proxy(target, handler); // 使用proxy代理了一个空对象 proxy对象具有响应式


const target2 = {name: "ts",age: "18"};
const handler2 = {
  get(target, key, receiver) {
    console.log(`访问属性${key}`)
    return Reflect.get(target, key, receiver)
  },
  set(target, key, value, receiver) {
    console.log(`设置属性${key}`)
    return Reflect.set(target, key, value, receiver)
  }
};
const proxy2 = new Proxy(target2, handler2); // 使用proxy代理了一个handler2对象 handler2对象中设置了get和set属性
console.log('proxy2.name', proxy2.name)
proxy2.name = 'jkl';
proxy2.sex = 'male';
console.log('proxy2',proxy2);
``
  • Object.defineproperty 与 proxy 的区别
  • 由 vue2 的响应式原理可以看出,vue 底层需要对 vue 实例的返回的每一个 key 进行 get 和 set 操作,无论这个值有没有被用到。所以在 vue 中定义的 data 属性越多,那么初始化开销就会越大。而 proxy 是一个惰性的操作,它只会在用到这个 key 的时候才会执行 get,改值的时候才会执行 set。所以在 vue3 中实现响应式的性能实际上要比 vue2 实现响应式性能要好
1:Object.defineproperty 初始化的时候拦截对象,设置为getset属性
const obj = {
  name: "wxs",
  age: 25,
};
Object.entries(obj).forEach(([key, value]) => {
  Object.defineProperty(obj, key, {
    get() {
      return value;
    },
    set(newValue) {
      console.log(`监听到属性${key}改变`);
      value = newValue;
    },
  });
});
obj.name = 11;
obj.age = 22;
obj.ak47 = "ak47";

1:输出结果 => 监听到属性name改变、监听到属性age改变

2: proxy 初始化的时候,有使用这个key值则get一下,有设置这个key值则set一下
const obj = {
    name:'wxs',
    age:25
}

const prxoyTarget = new Proxy(obj,{
    get(target,key){
        return target.key
    },
    set(target,key,value){
        console.log(`监听到属性${key}需要改成${value}`)
        target[key] = value
    }
})

prxoyTarget.name = 11
prxoyTarget.age = 22
prxoyTarget.ak47 = 'ak47'

2:输出结果 => 监听到属性name需要改成11、监听到属性age需要改成22、监听到属性ak47需要改成ak47
  • 22
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值