Vue3总结

本文详细介绍了Vue3相比Vue2的优势,包括更好的性能、更小的体积和增强的TypeScript支持。重点讲解了Composition API、ref、toRef和toRefs的使用,并对比了Vue2和Vue3在createApp、emits、模板语法等方面的差异。此外,还探讨了Vue3的响应式原理、watch与watchEffect的区别以及如何在setup中获取组件实例。
摘要由CSDN通过智能技术生成

Vue3 比 Vue2 什么优势?

  • 性能更好
  • 体积更小
  • 更好的 TS 支持
  • 更好的代码组织
  • 更好的逻辑抽离 

Composition API 的优点

  • 更好的代码组织
  • 更好的逻辑复用
  • 更好的类型推导

如何理解 ref、toRef 和 toRefs

ref

  • 生成值类型响应式数据
  • 可用于模板和 reactive
  • 通过 .value 修改值 
  • ref值变量尽量使用 Ref 后缀,如:ageRef

通过 ref 可获取 DOM 节点

toRef

  • 创建一个 ref 对象,其value值指向另一个对象(reactive 封装)中的某个属性
  • 两者保持引用关系
  • 语法:const name = toRef(person,'name')

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

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

 ref、toRef 和 toRefs 的最佳使用方式

  • 用 reactive 实现对象的响应式,用 ref 实现值类型的响应式
  • setup 中返回 toRefs(state)  ,或者 toRef(state,'xxx')
  • ref 的变量命名都用 xxxRef
  • 合成函数返回响应式对象时,使用 toRefs

为何需要 ref

  • 不使用 ref ,值类型会丢失响应式
  •  如在 setup、computed、合成函数,都有可能返回值类型
  • Vue 不定义 ref,用户将自造 ref,反而混乱

为何需要 .value

  • ref 是一个对象(不丢失响应式),value 用来存储值
  • 通过 .value 属性的 get 和 set 实现响应式
  • 用于模板、reactive 时,不需要 .value,其他情况都需要

为何使用toRef 和 toRefs

  • 初衷:在不丢失响应式的情况下,解构 reactive 的响应式对象

vue3升级了哪些重要的功能(与 vue2 的区别)

vue3 启用 createApp,vue2使用的是 new Vue

vue3 新增 emits 属性,使用需要先声明

vue2使用 $emit(自定义事件)

多事件处理

注意:不能采用简写形式,必须写成函数

vue3 template标签中无需根节点

移除 .sync(用于 prop 的双向绑定)

异步组件

Teleport(任意门)

Composition API

  • reactive
  • ref、toRef、torefs
  • readonly
  • watch 和 watchEffect
  • setup
  • 生命周期钩子

vue3的响应式

vue2 和 vue3 响应式对比,见vue2 总结

Proxy 的基本使用

语法:  new Proxy( target, handler )

  • target: 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
  • handler 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
    • get( target, key, receiver)
    • set( target, key, val, receiver)
    • deleteProperty( target, key)

const reactive = function(data){
  //排除值类型数据
  if(typeof data !== 'object' || data == null){
    return data
  }
  
  const proxyObj = {
    get(target, key, recevie){   //target:即传入的对象 data   key:读取的键名  recevie:整个Proxy对象
      const ownKeys = Reflect.ownKeys(target)
      //排除使用数组方法时,多输出的方法名称
      if(ownKeys.includes(key)){
        console.log('get',key)
      }

      const result = Reflect.get(target, key, recevie)
      
      //深层监听
      //性能提升:获取到哪层,哪层触发响应式
      return reactive(result)
    },
    set(target, key, val, recevie){  //target:即传入的对象 data   key:修改的键名  val:修改的值(新,即 newval)  recevie:整个Proxy对象
      //oldval  和  newval 相同时,直接输出
      if(target[key] === val){
        return true
      }

      //判断是否为新增的属性
      const ownKeys = Reflect.ownKeys(target)
      if(ownKeys.includes(key)){
        console.log('已存在的属性')
      }else{
        console.log('新的属性')
      }
      const result = Reflect.set(target, key, val, recevie)
      return result
    },
    deleteProperty(target, key){  //target:即传入的对象 data    key:想要删除的键名
      const result = Reflect.deleteProperty(target, key)
      return result
    }
  }
  const result = new Proxy(data,proxyObj)
  return result
}

const data = {
  name:'zhangsan',
  age:18,
  hobby:{
    PE: 'swim',
  },
}

// const data = ['a','b','c','d']

const rea = reactive(data)
// rea.name = 'lisi',
// rea.push('v')
// console.log(rea.name)
console.log(rea.hobby.PE)

watch 和 watchEffect 的区别

  • 两者都可以监听 data 属性的变化
  • watch 需要明确监听哪个属性
  • watchEffect 会根据其中的属性,自动监听其变化,初始化时一定会执行一次
//情况一:监视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配置有效

  • watch的套路是:既要指明监视的属性,也要指明监视的回调。
  • watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
  • watchEffect有点像computed:
    • 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
    • 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
//初始话时一定会执行一次
watchEffect(()=>{
    const x1 = sum.value
    const x2 = person.age
    console.log('watchEffect配置的回调执行了')
})

sutup 中如何获取组件实例(this)

  • 在 setup 和 composition API 中没有 this
  • 可通过 getCurrentInstance 获取当前实例(this)
  • 使用 Options API 可照常使用 this

 

Vue3 为何比 Vue2 快

  • Proxy 响应式:vue2 采用的响应式是一次性递归所有,计算量大,vue3 采用的响应式用到哪里递归到哪里,单次计算量小,运行速度快;
  • PatchFalg:编译模板时,给动态模板做标记,且为其区分不通的类型,在执行 diff 算法时,可以区分静态节点,以及不同类型的动态节点,diff 算法会跳过静态文本节点的比较;
  • hoistStatic:将静态节点的定义提升到父作用域,缓存起来,多个相邻的静态系节点会被合并起来,典型的用空间换时间的做法
  • cacheHandler:缓存事件
  • SSR(服务端渲染)优化:静态节点直接输出,绕过 vdom,动态节点依旧渲染;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值