Vue爬坑记-----(3)Vue3组合式API

388 阅读3分钟

setup 函数

所有组合式api都需要在这个函数中使用,个人理解这个函数相当于一个全新的生命周期,他的执行时机为组件创建之前,所以在这个函数中没法使用this获取到当前组件实例,该函数的返回值为一个对象,该对象的所有属性都可以在组件模板中直接访问,这里要说明的是setup函数只会执行一次

export default {
  components: {  },
  props: {
    user: {
      type: String,
      required: true
    }
  },
  setup(props) {
    console.log(props) // { user: '' }

    return {} // 这里返回的任何内容都可以用于组件的其余部分
  }
  // 组件的“其余部分”
}

WARNING

在 setup 中你应该避免使用 this,因为它不会找到组件实例。setup 的调用发生在 data property、computed property 或 methods 被解析之前,所以它们无法在 setup 中被获取。官网介绍

使用setup函数的时候需要注意的地方有
1、由于在执行 setup函数的时候,还没有执行 Created 生命周期方法,所以在 setup 函数中,无法使用 data 和 methods 的变量和方法

2、由于我们不能在 setup函数中使用 data 和 methods,所以 Vue 为了避免我们错误的使用,直接将 setup函数中的this修改成了 undefined

3、setup函数只能是同步的不能是异步的

在使用Vue3开发的过程中,大部分操作都在该函数中完成,所以Vue提供了setup语法糖:

<template>
    <div>
        {{name}}
    </div>
</template>
<script setup>
    //在这里定义的变量函数都可以直接在模板中使用
    const name = 'zhangsan';
</script>

常用的组合式API(感觉像是React里的Hooks)

以下所有代码片段中的hooks都已使用unplugin-auto-import/vite插件自动导入

ref和reactive

两者的作用都是可以创建一个响应式变量,所谓响应式变量就是改变该变量的值之后会触发Vue的组件更新机制,ref是reactive的一层封装ref(10)相当于reactive({value:10}),所以ref创建的变量如果需要在模板外访问其值,就需要通过.value的方式获取,vue也提供了$ref的语法糖,但是需要在vite.config.js中配置开启使用

//vite.config.js
.....
plugins:[
    vue({
       script: {
         refSugar: true, // 开$ref语法糖 可以使用$ref代替ref.value
       },
     }),
]
.....

使用方式和react中的useState和useMemo差不多,直接调用

const a = ref(true);
const obj = reactive({name:'zhangsan',age:18});

至于两者之间的的关系详解可以参考

Vue3.0 Ref与Reactive的区别

defineProps

这个函数是vue提供的在setup中用来获取父组件传递过来的数据
在父组件中:

<CildComponent v-bind="childProps"/>

在子组件中:

const props = defineProps({
    a:{
        type:Number,
        default:0
    },
    b:{
        ....
    }
})

watch

作用和用法和Vue2中的watch属性一样,用来监听某个响应式变量的变化

const counter = ref(0)
watch(counter, (newValue, oldValue) => {
  console.log('The new counter value is: ' + counter.value)
})

computed

作用和用法跟Vue2中的计算属性一样

const counter = ref(0);
//简写
const twiceTheCounter = computed(() => counter.value * 2);
//或者 
const twiceTheCounter = computed({
    get(){},
    set(value){}
});

provide和inject

这两个hooks是用于组件跨层级传值
provide用法:

const name = ref('zhangsan');
const vm = provide('name',name); // 这里provide传了一个响应式值 不能用$ref语法糖
// provide([key:symbol],value) 返回值为应用实例

inject用法

const name = inject('name');
// inject([key],[defaultValue可选])返回值为key所对应的值

defineEmits

用来定义emits,使用方法如下
子组件:

const emits = defineEmits(['fun','fun1']);
onMounted(()=>emits(fun,123));

父组件:

<template>
    <ChildComponent @fun="handle" />
</template>
<script setup>
    const handle = val=>console.log(val)
</script>

这里需要提到的是假如父子组件嵌套有多级并且在每一级定义了相同的事件,那么在emits触发事件的时候会从emits触发事件的上一级开始依次触发事件处理函数,类似于原生当中的事件冒泡

记录一个开发小技巧:使用事件和计算属性为自己的组件实现v-model指令,v-model并不是适用于所有的元素,他只适用于表单元素但是我们可以通过一些手段为任何一个组件实现v-model 这个指令,v-model实际上可以算是v-bindv-on的语法糖,在Vue3中可以使用v-model绑定多个值,实现方式如下:
父组件:

<template>
    <ChildComponent v-model="name" v-model:age="age" />
</template>
<script setup>
   const name = ref('zhangsan');
   const age = ref(18);
   /**
       上面的v-model="name" 相当于 v-bind="modelValue" + v-on:updateModelValue="(value)=>name=value" modelValue为默认key
       上面的v-model:age="age" 相当于 v-bind="age" + v-on:updateAge="(value)=>age=value"
   **/
</script>

子组件:

<template>
    <div>
        <input v-model="nameField" />
        <input v-model="ageField" />
    </div>
</template>
<script setup>
   const emits = defineEmits(['update:modelValue','update:age']);
   const props = defineProps({
       name:{
           type:String,
           default:''
       },
       age:{
           type:String,
           default:0
       }
   });
   const nameField = computed({
       get:()=>props.name,
       set:val=>emits('update:modelValue',val)
   });
   const ageField = computed({
       get:()=>props.age,
       set:val=>emits('update:age',val)
   });
</script>

生命周期

在Vue3中 大部分生命周期都提供了相应的hooks以供在setup函数中调用,这是官方文档提供的生命周期对应的hooks

选项式 APIHook inside setup
beforeCreateNot needed*
createdNot needed*
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
errorCapturedonErrorCaptured
renderTrackedonRenderTracked
renderTriggeredonRenderTriggered
activatedonActivated
deactivatedonDeactivated