Vue3学习笔记

527 阅读4分钟

一、常用组合式api

setup

vue2中的数据、方法、生命周期等写在setup中
vue2可以调用vue3中的数据;vue3不能读取vue2配置的数据;vue2和vue3不要混用
setup有两种返回方式:

//返回渲染函数(了解)
return ()=>{
  return h('h1',"sss")
}
//返回一个对象
return {name,age,sayHellow}

注意:1、setup不能是一个async函数 若被async修饰,返回值不再是对象,而是promise(可以是Promise实例,但是需要Suspense和异步组件的配合。
2、setup的执行时机:beforeCreate之前执行一次,this是undefined
3、setup接收两个参数,prop和context
prop:接收组件外部属性
context:上下文对象 {attrs:接收外部属性中,props未声明的属性,slots:接收插槽,emit:相当于this.$emit}

ref函数

作用:实现数据响应式 defineProperty的getter和setter
原理:将基本数据类型数据加工生成RefImpl引用实现的实例对象(引用对象)
引用类型数据加工成Proxy代理对象(内部引用reactive函数)

reactive函数

作用:定义对象类型的响应式数据

ref和reactive对比

ref定义基本数据类型 reactive定义对象类型数据 ref可定义对象数据类型,内部通过reactive
ref通过object.defineProperty()的get与set实现响应式,reactive通过Proxy实现数据劫持,通过Reflect操作对象数据
ref需要通过value读取数据 reactive不需要

vue2和vue3数据响应式对比

vue2:对象类型:通过Object.defineProperty()读取数据,进行数据劫持
数组类型:通过重写更新数组的一系列方法实现拦截
存在问题:新增属性,删除属性,界面无法更新 解决方法:新增:vue.set/this.$set方法 删除:this.$delete/vue.delete方法
直接通过数据下标修改数组,界面无法更新 解决方法:vue.set/this.$set方法 array.splice方法
vue3:利用window内置构造函数Proxy,拦截对象中任意属性的变化(get,set,deleteProperty),通过Reflect对被代理对象的属性进行操作

vue2需要写根标签,vue3不需要,内部将多个标签包含在Fragment虚拟元素中
vue2中的Vue.prototype为vue3中的app.config.globalProperties

//main.js中定义
const app = createApp(App)
app.use(store).use(router).mount('#app')
app.config.globalProperties.$http=()=>{
    console.log("ddd");
}
//组件中使用
import {getCurrentInstance} from "vue"
const {proxy} = getCurrentInstance()
function testhttp(){
  proxy.$http()
}

computed

setup(){
    let person=reactive({
      firstName:"zs",
      secondName:"ls",
    })
    //简写形式
    let fullName1=computed(()=>{
      return person.firstName+"_"+person.secondName
    })
    //完整写法
    let fullName2=computed({
      get(){
        return person.firstName+"_"+person.secondName
      },
      set(value){
        person.firstName=value.split("_")[0]
        person.secondName=value.split("_")[1]
      }
    })
    return {person,fullName1,fullName2}
  }

watch

watch(监视对象,回调函数,配置对象)

setup(){
    let sum=ref(0)
    let msg=ref("whh")
    let person=reactive({
      name:"zs",
      age:18,
      job:{
        a:{
          b:20
        }
      }
    })
    // 1、监视ref定义的一个基本数据类型
    watch(sum,(newvalue,oldvalue)=>{
      console.log("新值为"+newvalue,"旧值为"+oldvalue);
    },{immediate:true})
    // 2、监视ref定义的多个基本数据类型
    watch([sum,msg],(newvalue,oldvalue)=>{
      console.log(newvalue,oldvalue);
    },{immediate:true})
    // 3、监视reactive定义的一个对象  拿不到旧值,且不需要配置deep已经深度监视了,无法关闭
    watch(person,(newvalue,oldvalue)=>{
      console.log(newvalue,oldvalue);
    })
    // 4、监视reactive定义对象的某一个属性
    watch(()=>person.age,(newvalue,oldvalue)=>{
      console.log(newvalue,oldvalue);
    })
    // 5、监视reactive定义对象的某些属性
    watch([()=>person.name,()=>person.age],(newvalue,oldvalue)=>{
      console.log(newvalue,oldvalue);
    })
    // 6、特殊情况 监视reactive定义对象中的某个对象属性时,需要开启深度监视
    watch(()=>person.job,(newvalue,oldvalue)=>{
      console.log(newvalue,oldvalue);
    },{deep:true})

    return {sum,msg,person}
  }

watchEffect

不需要指明监视哪个属性,监视的回调中使用到哪个属性,就监视哪个属性
与computed对比:computed更注重计算出来的值,需要return
watchEffect更注重回调函数的执行,不需要return

setup(){
    let sum=ref(0)
    let msg=ref("whh")
    let person=reactive({
      name:"zs",
      age:18,
      job:{
        a:{
          b:20
        }
      }
    })
    // 1、监视ref定义的一个基本数据类型
    watchEffect(()=>{
      const x1=sum.value
      const x2=person.job.a.b
      console.log("watchEffect执行了");
    })
    return {sum,msg,person}
  }

vue3生命周期

几乎与vue2相同,卸载除外,vue2中的beforeDestory改为beforeUnmount,Destoryed改为Unmounted
使用方式:通过配置项形式使用(与vue2相同)
通过组合式api在setup中使用:
beforeCreate=>setup()
create=>setup()
beforeMount=>onBeforeMount
mounted=>onMounted
beforeUpdate=>onBeforeUpdate
Updated=>onUpdated
beforeUnmount=>onBeforeUnmount
Unmounted=>onUnmounted
同时写的情况同一个生命周期setup中的先执行

自定义hook函数

作用:将setup中使用的组合式api进行封装,实现复用

toRef toRefs

作用:创建一个ref对象,将其value指向另一个对象中的某个属性
const 属性=toRef(对象,“属性”) const 对象=toRefs(对象)

二、其他组合式api

shallowReactive:和reactive的区别:只处理对象最外层属性的响应式
shallowRef:和ref的区别:只处理基本数据类型的响应式,不进行对象的响应式处理
readonly:响应式数据变为只读(深只读)
shallowReadonly:响应式数据变为只读(浅只读)
toRaw:将reactive生成的响应式对象转为普通对象
markRaw: 标记一个对象,使其永远不会成为响应式对象
customRef:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显示控制
provide和inject:实现祖孙间通信,父组件provide提供数据,子组件inject来使用
provide(“提供的属性名”,属性) inject(“提供的属性名”)
判断响应式数据:
isRef:检查一个值是否为ref对象
isReactive:检查一个对象是否为reactive创建的对象
isReadonly:检查一个对象是否是由readonly创建的只读代理
isProxy:检查一个对象是否由reactive或者readonly方法创建的代理

三、新的组件

Fragment:虚拟容器
Teleport:将内容传送到指定容器,<teleport to="body"/to="#id选择器">组件内容
Suspense:

import Child from './components/Child'//静态引入
import {defineAsyncComponent} from 'vue'
const Child = defineAsyncComponent(()=>import('./components/Child'))//异步引入
<Suspense>
  <!-- 异步加载组件 -->
  <template v-slot:default>
    <Child/>
  </template>
  <!-- 异步组件未展示时显示的界面 -->
  <template v-slot:fallback>
    <h1>加载中...</h1>
  </template>
</Suspense>

24kcs.github.io/vue3_study/…