65 - vue3 - 组合式API

一. 组合式API-setup选项

        1. setup选项的写法和执行时机
                (1). 图片示例

                (2). 代码示例

        2. setup选项中写代码的特点

                问题: 每次都return,很麻烦

                (1). 图片示例

        (2). 代码示例

        3. <script setup> 语法糖

                解决每次都return问题

                (1). 图片示例

        (2). 代码示例

        4. <script setup> 语法糖原理

        5. 总结

        (1). setup选项的执行时机?
                beforeCreate钩子之前 自动执行
        (2). setup写代码的特点是什么?
                定义数据 +函数 然后以对象方式return
        (3). <script setup>解决了什么问题?
                经过语法糖的封装更简单的使用组合式AP
        (4). setup中的this还指向组件实例吗?
                指向undefined

二. 组合式API-reactive 和 ref函数

        推荐: 以后声明数据,统一使用ref

1. reactive()
(1).作用:

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

(2).核心步骤:

(3). 代码示例
<script setup>
// reacyive: 接收一个对象类型的数据,返回一个响应式的对象
import { reactive } from 'vue'
const state = reactive({
  count:100
})

const setCount=()=>{
  state.count++
}
</script>

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

2. ref()
(1). 作用:

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

(2). 核心步骤

(3). 代码示例
<script setup>
// 2. ref: 接收简单类型 或 复杂类型,返回一个响应式的对象
// 本质: 是在原有传入数据的基础上,外层包了一层对象,包成了复杂类型对象
// 底层: 包成复杂类型之后,在借助 reactive 实现的响应式
// 注意点: 
//      1. 脚本中访问数据,需要通过 .value
//      2. 在template中, .value不需要加(帮我们扒了一层)

// 推荐: 以后声明数据,统一使用ref => 统一了编码规范
import {ref} from 'vue'
const count = ref(0)
const setCount=()=>{
  count.value++
}
</script>

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

3. 总结

        (1).reactive和ref函数的共同作用是什么?

                用函数调用的方式生成响应式数据        

        (2).reactive vs ref ?               

                 ①.reactive不能处理简单类型的数据

                 ②.ref参数类型支持更好但是必须通过.value访问修改

                 ③.ref函数的内部实现依赖于reactive函数       

         (3).在实际工作中推荐使用哪个?                

                 推荐使用ref函数,更加灵活统一

三.组合式API- computed计算属性函数

计算属性基本思想和Vue2的完全一致,组合式API下的计算属性只是修改了写法

1. 核心步骤: 

        (1). 导入computed函数
        (2). 执行函数在回调参数中return基于响应式数据做计算的值,用变量接收

<script setup>
    // 导入
    import {computed} from 'vue'
    // 执行函数 变量接收 在回调参数中 return计算值
    const computeState = computed(() => {
    return 基于响应式数据做计算之后的值
})
<script>
2. 代码示例
<script setup>
// const 计算属性 = computed(() => {
// return 计算返回的结果
// })


import { computed,ref } from 'vue'
// 声明数据
const list = ref([1, 2, 3, 4, 5, 6, 7, 8])

// 基于list派生一个计算属性,从list中过滤出 > 2
const computedList = computed(() => {
  return list.value.filter(item => item > 2)
})

// 定义一个修改数组的方法
const addFn=()=>{
  list.value.push(666)
}
</script>

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

        (1).计算属性中不应该有"副作用"
                比如异步请求/修改dom

        (2).避免直接修改计算属性的值
                计算属性应该是只读的,特殊情况可以配置 get set

四. 组合式API-watch 侦听函数

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

俩个额外参数: 1.immediate (立即执行)  2.deep(深度侦听)

1. 基础使用-侦听单个数据

        (1). 导入watch函数

        (2). 执行watch函数传入要侦听的响应式数据(ref对象)和回调函数

<script setup>

//1. 导入watch
import { ref, watch } from 'vue'
const count = ref(0)

//2. 调用watch 侦听变化
watch(count,(newValue, oldValue) => {
    console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)
})

</script>
2. 基础使用-侦听多个数据

说明:同时侦听多个响应式数据的变化,不管哪个数据变化都需要执行回调函数

<script setup>

import { ref, watch ] from 'vue'
const count = ref(0)
const name = ref('cp')

// 侦听多个数据源
watch(
    [count,name],
    ([newCount, newName], [oldCount, oldName]) => {
        console,log('count或者name变化了',[newCount,newName],[oldCount, oldName])               
   }
)
</script>
3. 基础监听-代码示例
<script setup>
import { ref,watch } from 'vue'
const count = ref(0)
const nickname = ref('张三')

const changeCount = () => {
  count.value++
}
const chageNickname=()=>{
  nickname.value='李四'
}

//1. 监视单个数据的变化
//    watch(ref对象,(newValue,oldValue) => {...})
// watch(count,(newValue,oldValue)=>{
//   console.log(newValue,oldValue)
// })

// 2. 监视多个数据的变化
//     watch([ref对象1,ref对象2],(newArr,oldArr) => {...})
 watch([count,nickname],(newArr,oldArr)=>{
  console.log(newArr,oldArr)
 })

</script>

<template>
  <div>{{ count }}</div>
  <button @click="changeCount">改数字</button>
  <div>{{ nickname }}</div>
  <button @click="chageNickname">改昵称</button>
</template>
4. immediate 参数

   说明:在侦听器创建时立即触发回调,响应式数据变化之后继续执行回调

const count= ref(0)
watch(count,() =>{
    console.log('count发生了变化')
    },{
    immediate: true
})
<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
const nickname = ref('张三')

const changeCount = () => {
  count.value++
}
const chageNickname = () => {
  nickname.value = '李四'
}

// 3. immediate 立刻执行
 watch(count,(newValue,oldValue)=>{
   console.log(newValue,oldValue)
 },{
   immediate:true
 })


</script>

<template>
  <div>{{ count }}</div>
  <button @click="changeCount">改数字</button>
  <div>{{ nickname }}</div>
  <button @click="chageNickname">改昵称</button>
 
</template>
5. deep 参数

        深度监视, 默认 watch 进行的是 浅层监视

watch(userInfo, (newValue) => {
  console.log(newValue)
}, {
  deep: true
})
<script setup>
import { ref, watch } from 'vue'

// 4. deep 深度监视, 默认 watch 进行的是 浅层监视
//  const ref1 = ref(简单类型) 可以直接监视
//  const ref2 = ref(复杂类型) 监视不到复杂类型内部数据的变化
const userInfo = ref({
  name: 'zs',
  age: 18
})

const setUserInfo = () => {
  // 修改了 userInfo.value 修改了对象的地址,才能监控到
  // userInfo.value = {name: 'ls',age: 19}
  userInfo.value.age++
}

//deep  深度监视
watch(userInfo, (newValue) => {
  console.log(newValue)
}, {
  deep: true
})
</script>

<template>
  <div>{{ userInfo }}</div>
  <button @click="setUserInfo">修改userInfo</button>
</template>
6. 精确侦听对象的某个属性

需求:在不开启deep的前提下,侦听age的变化,只有age变化时才执行回调

<script setup>
import { ref, watch } from 'vue'
const userInfo = ref({
  name: 'zs',
  age: 18
})

const setUserInfo = () => {
  // 修改了 userInfo.value 修改了对象的地址,才能监控到
  // userInfo.value = {name: 'ls',age: 19}
  userInfo.value.age++


// 5. 对于对象中的属性进行监视
watch(() => userInfo.value.age,(newValue,oldValue)=>{
    console.log(newValue,oldValue)
})
</script>

<template>
  <div>{{ userInfo }}</div>
  <button @click="setUserInfo">修改userInfo</button>
</template>
7. 总结

        (1).作为watch函数的第一个参数,ref对象需要添加.value吗?

                不需要,第一个参数就是传 ref 对象

        (2).watch只能侦听单个数据吗?
                单个 或者 多个
        (3).不开启deep,直接监视 复杂类型,修改属性 能触发回调吗?

                不能,默认是浅层侦听

        (4).不开启deep,精确侦听对象的某个属性?                

                可以把第一个参数写成函数的写法,返回要监听的具体属性

五. 组合式API-生命周期函数

1. 选项式 vs 组合式

2. 代码示例
<script setup>
import { onMounted } from 'vue';


// beforeCreate 和 created 的相关代码
// 一律放在 setup中执行

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


// 如果有些代码需要在mounted生命周期中执行
onMounted(()=>{
  console.log('mounted生命周期函数-逻辑1')
})

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

<template></template>

六. 组合式API-父子通信

1. 组合式API下的父传子

基本思想:

        (1). 父组件中给子组件绑定属性

        (2). 子组件内部通过props选项接收

代码示例:

2. defineProps原理

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

3.  组合式API下的子传父

基本思想
        1.父组件中给子组件标签通过@绑定事件
        2.子组件内部通过 emit 方法触发事件

代码示例:

4. 总结

父传子
        1.父传子的过程中通过什么方式接收props?                

                defineProps({ 属性名: 类型])        

        2.setup语法糖中如何使用父组件传过来的数据?

                const props = defineProps({ 属性名: 类型})

                props.xxx

子传父
        1.子传父的过程中通过什么方式得到emit方法?

                defineEmits([事件名称])

        2.怎么触发事件               

                 emit('自定义事件名',参数)

七. 组合式API-模板引用

1. 模板引用的概念

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

2. defineExpose()

默认情况下在<script setup>语法糖下组件内部的属性和方法是不开放给父组件访问的

可以通过defineExpose编译宏指定哪些属性和方法允许访问

3. 代码示例

4. 总结

        (1). 获取模板引用的时机是什么?
                组件挂载完毕

         (2). defineExpose编译宏的作用是什么?
                显式暴露组件内部的属性和方法

八. 组合式API-provide和inject

1. 作用和场景

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

2. 跨层级传递普通数据

        (1).顶层组件通过provide函数提供数据
        (2).底层组件通过inject函数获取数据

3. 跨层级传递响应式数据

在调用provide函数时,第二个参数设置为ref对象

4. 跨层级传递方法

顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件中的数据

5. 代码示例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值