本文介绍: Vue 3 组合式 API【详解】

一、setup 选项

<script>
export default {
  /**
   * 1、setup 执行时机早于 beforeCreate
   * 2、setup 中无法获取 this
   * 3、数据和函数需要在 setup 最后 return,才能在模板中使用
   * 4、可以通过 setup 语法糖简化代码
   */
  setup(){
    // console.log('setup function', this)

    // 数据
    const msg = 'Hello Vue3'
    const logMsg = () => {
      console.log(msg)
    }

    return{
      msg,
      logMsg
    }
  },
  beforeCreate(){
    // console.log('beforeCreate function')
  }
}
</script> 

若未 return 在浏览器也会有警告  

每次都需要 return,若数据与函数的量很大,就会很麻烦,所以可以通过语法糖来简化代码  

<script setup>
const msg = 'Hello Vue3'
const logMsg = () => {
  console.log(msg)
}
</script>

<template>
  <div>{{ msg }}</div>
  <button @click="logMsg"></button>
</template>

二、reactive 和 ref 函数  

reactive():接收对象类型数据的参数传入并返回一个响应式的对象 

步骤:

  • 从 vue 中导入 reactive 函数

  • <script setup> 中执行 reactive 函数并传入类型为对象的初始值,并使用变量接收返回值

<script setup>
 import { reactive } from 'vue'
 const state = reactive({
   count: 100
 })
 const setCount = () => {
   state.count++;
 }
</script>

<template>
  <div>
    <!-- 
      <div>{{ state.count }}</div>
      <button @click="setCount">+1</button> 
    -->
  </div>
</template>

ref():接收简单类型或对象类型的数据传入并返回一个响应式的对象

底层是将简单类型数据包装成对象类型的数据,然后借助 reactive 实现响应式  

步骤:

  • 从 vue 中导入 ref函数

  • <script setup> 中执行 ref函数并传入类型为对象的初始值,并使用变量接收返回值

<script setup>
import { ref } from 'vue'

const count = ref(0)
const setCount = () => {
  // 访问数据需要通过 .value【template中不需要】
  count.value++;
}
</script>

<template>
  <div>
    <div>{{ count }}</div>
    <button @click="setCount">+1</button>
  </div>
</template>

三、computed 

步骤:

  • 导入 computed 函数

  • 执行函数在回调函数中 return 基于响应式数据做计算的值,用变量接收

<script setup>
import { computed, ref } from 'vue'

const list = ref([1, 2, 3, 4, 5, 6, 7, 8])

const computedList = computed(() => {
  // 只读
  return list.value.filter(item => item > 2)
})

const addFn = () => {
  list.value.push(9)
}
</script>

<template>
  <div>
    <div>原始数据:{{ list }}</div>
    <div>计算后数据:{{ computedList }}</div>
    <button @click="addFn">修改</button>
  </div>
</template>

以上创建的是一个 只读 的计算属性 ref,若要创建一个 可写 的计算属性 ref,可以这样做:  

const count = ref(1)
const plusOne = computed({
  get: () => count.value + 1,
  set: (val) => {
    count.value = val - 1
  }
})

plusOne.value = 1
console.log(count.value) // 0

在计算属性中不要进行异步请求或这修改 DOM 的操作

避免直接修改计算属性的值

四、watch 

侦听一个或者多个数据的变化,数据变化时执行回调函数  

<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
const name = ref('cp')

const setCount = () => {
  count.value++;
}

const setName = () => {
  name.value = '张三 - 李四'
}

// 侦听单个数据
watch(count, (newValue, oldValue) => {
  console.log(`count 值发生了变化,新值为 ${newValue},旧值为 ${oldValue}`)
})
// 侦听多个数据
watch(
  [count, name],
  ([newCount, newNode], [oldCount, oldName]) => {
    console.log('count 或 name 发生了变化', [newCount, newNode], [oldCount, oldName])
})
</script>

<template>
  <div>{{ count }}</div>
  <button @click="setCount">改数字</button>
  <div>{{ name }}</div>
  <button @click="setName">改名字</button>
</template>

两个参数:

  • immediate(立即执行)

  • deep(深度侦听)  

watch(count, ()=>{
  console.log('count变了')
},{
  immediate: true
})

watch 可以直接监视简单类型数据

const ref = ref(简单类型)

 watch 无法监视复杂类型内部数据的变化

const ref = ref(复杂类型)
watch(复杂类型对象, (newValue) => {
	console.log(newValue);
}, {
	deep: true
})

若没有添加 deep 参数,默认的是监听对象的地址是否变化,除非修改了对象的地址,否则不会被监听到。

若要监听复杂类型对象内部属性的变化,则需要添加 deep 参数,即可对其进行监听

精确监听对象的某个属性

在不开启 deep 的前提下,侦听对象属性的变化,只有属性变化时才执行回调

// 精确侦听某个属性
const info = ref({
  name: 'cp',
  age: 18
})
watch(
  () => info.value.age,
  () => console.log('age变了')
)

五、生命周期函数 

选项式 API 组合式 API
beforeCreate/created setup
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBreforeUpdate
update onUpdate
beforeUnmount onBeforeUnmount
unmounted onUnmounted
<script setup>
import { onMounted } from "vue"

// 一进入页面就调用
const getList = () => {
  setTimeout(() => {
    console.log('发送请求,获取列表数据')
  }, 2000)
}
getList()

// 在 mounted 时执行
onMounted(() => {
  console.log('mounted 生命周期函数 - 逻辑1')
})
// 写成函数的调用方式,可以调用多次,并不会冲突,而是按照顺序依次执行
onMounted(() => {
  console.log('mounted 生命周期函数 - 逻辑2')
})
</script>

六、父子通信 

1、父传子 

基本思想:

  • 父组件给子组件绑定属性

  • 子组件内部通过 props 选项接收  

defineProps 原理:编译阶段的一个标识,实际编译器解析时,遇到后会进行编译转换  

2、子传父 

基本思想:

  • 父组件中给子组件标签通过 @绑定事件

  • 子组件内部通过 emit 方法触发事件  

七、模板引用

通过 ref 标识获取真实的 DOM 对象或者组件实例对象  

步骤:

  • 调用 ref 函数生成一个 ref 对象

  • 通过 ref 标识绑定 ref 对象到

<script setup>
import { ref } from 'vue'
// 通过 ref 函数获得一个 ref 对象
const h1Ref = ref(null)
</script>

<template>
      <!-- 通过 ref 标识绑定 ref 对象 -->
      <h1 ref="h1Ref">我是 DOM 标签 h1</h1>
</template>

获取模板引用的时机:组件挂载完毕  

默认情况下在 <script setup> 语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过 defineExpose 编译宏指定哪些属性和方法允许访问  

<script setup>
import { ref } from 'vue'
const testMsg = ref('this is test msg')
defineExpose({
      testMsg
})
</script>

八、provide 和 inject  

作用:顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信  

跨层传递普通数据

  • 顶层组件通过 provide 函数提供数据

  • 底层组件通过 inject 函数获取数据

// 顶层组件
provide('key', 顶层组件中的数据)

// 底层组件
const msg = inject('key')

顶层组件可以向子层组件传递方法,底层组件调用方法修改顶层组件中的数据【实际在修改数据的依然是顶层组件】

一  叶  知  秋,奥  妙  玄  心

原文地址:https://blog.csdn.net/weixin_43551213/article/details/135985627

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_66367.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注