vue3常用组合式API

130 阅读3分钟
  • 本文旨在为大家快速梳理常用的组合式API作用和用法。主要包括ref,reactive,defineProps,defineEmits,watch,watchEffect。如有不甚详尽之处请各位大佬多多指出。
  • 本文将使用<script setup>作示例代码写法,<script setup>可以让代码变得更加精简,这也是现在开发 Vue 3 项目必备的写法。

ref

参考来源:cn.vuejs.org/api/reactiv…

接受一个内部值,返回一个响应式的、可更改的 ref 对象,此对象只有一个指向其内部值的属性 .value

import {ref} form 'vue';
export default {
    setup() {
        let count = ref(0);
        const handleClick = ()=>{
           count.value +=1;
        }
        return {
            count,
            handleClick
        }
    }
}

注意:

  1. 当你使用ref定义简单类型状态,不能使用解构取值(像这样const {value}=count),而必须使用xx.value(像这样count.value),否则会失去响应式!!
    这是因为JS中简单类型是存放在栈(栈堆是什么?)中的简单数据段,无法添加属性和方法。而使用解构实际上就是生成新对象,新对象的每个属性对应一个Ref对象,原响应式属性的操作被代理到新对象的ref上了。
  2. 当你使用ref定义对象(或引用类型),ref底层会将改对象通过reactive转为具有深层次响应式的对象。若要避免这种深层次的转换,请使用 shallowRef() 来替代。

reactive()

reactive()是提供实现响应式数据的方法。

reactive接收一个对象或数组的值,返回一个源对象的proxy对象。

import { reactive } from 'vue'
const objDemo = reactive({title: 'how',use:'some'})
const arrDemo = reactive([1, 2, 3])

csont funReact = () => {
      arr = [4,5,6]
      objDemo.title = 'what'
 }

注意: 1.基本类型数据不建议用reactive,会失去响应式并且报警告value cannot be made reactive: xx

  1. refreactive()对比

defineProps、defineEmits父子组件通信

参考来源:vue官网

// 父组件
<template>
  <Son :title=msg @edit="handleSonEdit"></Son>
</template>
<script setup>
  import {ref} from 'vue'
  import Son from './Son.vue'
  const msg = ref(111)
  const handleSonEdit = () =>{...}
</script>
// 子组件
<script setup>
import {ref,defineProps, defineEmits} from 'vue';
const props = defineProps(['title'])
const handleSomething = () => {
    console.log(props.title) //子组件取值
    defineEmits(["edit"]) // 把事件暴露出去
}
</script>

computed 计算属性

computed返回一个只读(或可写)的响应式ref对象,接收一个getter函数。也可以接收一个get加set函数(返回可写ref对象)。

<script setup>
import {ref, computed} from 'vue';
const count = ref(1)
let firstName = ref('Hazel')
let lastName = ref('cheng')
// 情况1. 只读对象-------
const plusOne = computed(() => count.value + 1)
// 此时的plusOne.value是只读的,不允许重新赋值
console.log(plusOne.value) // 打印结果2

// 情况2. 可读写对象-------
let plusName = computed({
  get: () => {return firstName + ' ' + lastName},
  set: (newValue) => {
    [firstName, lastName] = newValue.split(' ')
  }
})
plusName.value = 'John Doe'
console.log(plusName.value) // John Doe
console.log(firstName) // John
</script>

监听watch和watchEffect

watch(dependencies,callback)侦听一个或多个响应式数据源,并在数据源变化时才执行回调函数。返回值是一个用来停止该监听的函数。

// watch
const count = ref(0)
watch(
count, 
(count, prevCount) => {...},
{ deep: true } // 若监听引用类型要加deep,但reactive()无需加默认deep
)

const state = reactive({ count: 0 })
const myWatch = watch(
  () => state.count,
  (count, prevCount) => {...},
)
myWatch() //停止监听

watchEffect(dependencies,callback)侦听一个或多个响应式数据源,并在数据源变化时才执行回调函数。返回值是一个用来停止该监听的函数。默认情况下,侦听器将在组件渲染之前执行。设置 flush: 'post' 将会使侦听器延迟到组件渲染之后再执行。

const some = watchEffect(async (onCleanup) => {
  const { response, cancel } = doAsyncWork(id.value)
  onCleanup(cancel) // 未完成的请求,清除副作用
  data.value = await response
},
{ 
  flush: 'post',
}
)

some() // 当不再需要此侦听器时