一. 组合式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. 跨层级传递方法
顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件中的数据