9. 组合API-reactive函数
背景:ref函数定义的响应式数据在代码中使用要加.value,不是很方便。
作用:简化ref的写法(老是写xxx.value),它可以定义一个复杂数据类型,成为响应式数据。
使用步骤:
- 导入:从vue框架中导入
reactive
函数 - 调用:在setup函数中调用reactive函数并将对象数据传入
- 导出:在setup函数中把reactive函数调用完毕之后的返回值以对象的形式返回出去
演示代码:
<template> <p>姓名:{{stu.name}}, 公司:{{stu.company}},月薪:{{stu.salary}}</p> <button @click="double">月薪double</button> //步骤4,在模板使用 </template> <script> import { reactive } from 'vue' //步骤1:导入reactive export default { setup () { const stu = reactive({ //步骤2:给reactive传入数据 company: 'DiDi', name: '小王', salary:18000 }) const double = () => { stu.salary *= 2 console.log('stu.salary', stu.salary) } return { stu, //步骤3:导出 double } } } </script>
小结:reactive用来定义响应式数据
10. 组合API-toRefs函数
作用:定义转换响应式中所有属性为响应式数据,通常用于解构|展开reactive定义对象, 简化我们的在模板中的使用
格式:
增强版的结构赋值:在解构对象的同时,保留响应式的特点。 // 响应式数据:{ 属性1, 属性2 } let { 属性1, 属性2 } = toRefs(响应式数据)
代码举例:
<template> <p>{{name}}, {{company}}</p> <button @click="jumpToJD">jumpToJD</button> </template> <script> import { reactive, toRefs } from 'vue' export default { name: 'App', setup () { // 定义响应式对象 const stu = reactive({ company: 'DiDi', name: '小王' }) let { name, company } = toRefs(stu) const jumpToJD = () => { company.value = 'JD' name.value = '老王' console.log('toJD', company) } return { name, company, jumpToJD } } } </script>
10.1 toRefs与reactive配套使用。
在解构响应式数据时,还保持它的响应式特征。
const {p1, p2} = toRefs(reactive({p1, p2}))
11.如何确定什么时候用ref和reactive
定义响应式数据有两个方式:
- ref函数,常用于将简单数据类型定义为响应式数据
- 在代码中修改(或者获取)值时,需要补上.value
- 在模板中使用时,可以省略.value
reactive函数,常用于将复杂数据类型为响应式数据
12. 组合API-computed函数
作用:根据已有数据生成新的响应式数据。(对数据做处理)
步骤:
- 从vue框架中导入
computed
函数 - 在setup函数中执行computed函数,并传入一个函数,在函数中定义计算规则,并返回结果
- 把computed函数调用完的执行结果放到setup的return值对象中
格式:
import { computed } from 'vue' const 计算属性名 = computed(() => { return 响应式数据相关计算 })
代码示例:
<template> <p>姓名:{{name}}, 公司:{{company}}, 月薪:{{salary}}, 年薪{{total}}</p> <button @click="double">月薪double</button> </template> <script> import { ref, computed } from 'vue' 步骤1:导入computed export default { name: 'App', setup () { // 定义响应式对象 const company = ref('DiDi') const name = ref('小王') const salary = ref(18000) const double = () => { salary.value *= 2 } const total = computed(() => 12 * salary.value) //步骤2 计算规则 return { 步骤3 返回计算后的数据 name, company, total, salary, double } } } </script>
小结: vue3中的computed函数与vue2中的computed选项功能类似
13. 组合API-computed的高级用法
目标:掌握计算属性的高级用法:设置set属性, 会用v-model来绑定计算属性
格式:
const 计算属性 = computed({ get () { }, set () { } })
代码举例:
<template> <p>{{name}}, {{company}}, {{salary}}, {{total}}</p> <input type="text" v-model="total"> </template> <script> import { ref, computed } from 'vue' export default { name: 'App', setup () { // 定义响应式对象 const company = ref('DiDi') const name = ref('小王') const salary = ref(18000) const bonus = ref(20000) const double = () => { salary.value *= 2 } const total = computed({ set:(value) => { salary.value = value / 12 }, get: () => { return 12 * salary.value } }) return { name, company, total, salary, double } } } </script>
小结:
计算属性两种用法
- 给computed传入函数,返回值就是计算属性的值
- 给computed传入对象,get获取计算属性的值,set监听计算属性改变,做逻辑运算
14. 组合API-watch函数
是什么:监听,又叫侦听器
作用:监听响应式数据的变化,执行逻辑,和vue2差不多
步骤:
1.从vue框架中导入watch
函数
2.在setup函数中执行watch函数开启对响应式数据的监听
3.watch函数接收三个常规参数
3.1 第一个参数是:
对象,要监听的响应式数据;
数组,每个元素是响应式数据函数,返回你要监听变化的响应式数据
函数,返回你要监听变化的响应式数据
3.2 第二个参数是:响应式数据变化之后要执行的回调函数
3.3 第三个参数是: 一个对象,在里面配置是否开启立刻执行或者深度监听
特点:可以侦听一个,也可以侦听多个,侦听多个的时候使用数组的形式
14.1 侦听-开启立刻执行
watch的效果默认状态下,只有监听的数据发生变化才会执行回调,如果你需要在一上来的时候就立刻执行一次
设置: immediate: true
14.2 监听-复杂数据
如果watch的第一个参数是响应数据的话,它会默认监听其下所有属性的变化。
当我们监听的数据(第一个参数)是通过回调返回的一个对象的时候,默认状态下,对象内部的属性发生变化是不会被侦听到的,如果想让对象下面所有属性都能得到监听,需要开启deep
配置。
设置:deep:true
14.3侦听-复杂数据的指定属性
使用watch的时候,尽量详细的表明你到底要监听哪个属性,避免使用deep引起的性能问题,比如,仅只是想在stu对象的money属性的salary变化的时候执行回调,可以这么写 stu.money.salary
作用:watch用来侦听数据的变化。
格式:watch(数据|数组|get函数,(新值,旧值)=>{回调处理逻辑}, {immediate:true|false, deep: true|false})
15. 组合API-父子通讯
区别不大。唯一不同的是子组件中的使用
父传子:在setup种使用props数据 setup(props){ // props就是父组件数据 }
子传父:触发自定义事件的时候emit来自 setup(props,{emit}){ // emit 就是触发事件函数 }
在vue3.0中 v-model 和 .sync 已经合并成 v-model 指令
16. vue3中的v-model语法糖
有点变化:
<Son v-model="msg" /> <!--vue3中 上面的写法等价于下边---------------> <Son :modelValue="msg" @update:modelValue="val=>msg=val"/>`
小结:
在setup的两个参数中获取props和emit
父传子 props: :modelValue
子传父 emit @update:modelValue
vue3 中可以使用多个v-model
1. <Son v-model:xxx="msg"/> 2. -----相当于下边------------ 3. <Son :xxx="msg" @update:xxx="val=>msg=val"/>`
17. 组合API-依赖注入-祖先传后代
组件通信:可以实现跨越多个组件的数据传递,如爷孙组件的数据传递
注意:后代组件不能直接修改祖宗传过去的值,遵循的原则是谁提供的数据谁来改,可以让祖宗组件穿一个修改的方法
使用步骤:
- 祖先组件中提供数据:
provide('数据名1', 数据名)
- 后代组件中使用数据:
inject('数据名1')
小结: provide函数提供数据和函数给后代组件使
inject函数给当前组件注入provide提供的数据和函数
代码举例:
父组件:
<template> <div class="container"> <h1>父组件 {{money}} <button @click="money=1000">发钱</button></h1> <hr> <Son /> </div> </template> <script> import { provide, ref } from 'vue' import Son from './Son.vue' export default { name: 'App', components: { Son }, setup () { const money = ref(100) // 将数据提供给后代组件 provide provide('money', money) return { money } } } </script> <style scoped lang="less"></style>
子组件:
<template> <div class="container"> <h2>子组件 {{money}}</h2> <hr> <GrandSon /> </div> </template> <script> import { inject } from 'vue' import GrandSon from './GrandSon.vue' export default { name: 'Son', components: { GrandSon }, setup () { // 接收祖先组件提供的数据 const money = inject('money') return { money } } } </script> <style scoped lang="less"></style>
孙子组件:
<template> <div class="container"> <h3>孙组件 {{money}} <button @click="fn">消费20</button></h3> </div> </template> <script> import { inject } from 'vue' export default { name: 'GrandSon', setup () { const money = inject('money') return {money} } } </script> <style scoped lang="less"></style>
18. 组合API-依赖注入-后代改祖先
步骤:
- 祖先组件中提供数据&操作数据的函数f:
provide('函数f', 数据名)
- 后代组件中获取操作数据的函数f,并调用数据:
inject('函数f')
- 为方便多年后来查找,做一个极简版的
总结:
1.setup()函数是一个新的组件选项,里面按照功能划分,变量函数可以在一起写。
2.生命周期由8变成7个,setup函数合并了之前的前两个,在组件创建前的钩子前执行(快)
3.ref函数,把数据变成响应式的,在代码中使用要加.value 。简单和复杂类型都能处理。推荐
4.reactive函数,作用是把复杂类型数据变成响应式,当明确知道对象有什么属性时,如表单数据
5.toRefs函数,转换响应式中所有属性为响应式,通常用于解构,展开对象,简化在模板的使用,增强版的解构赋值,解构的同时,保留响应式的特点
6.computed函数,计算属性,注意使用格式(导入,定义,导出 )注意其高级用法(set、get),会用v-model来绑定计算属性
7.watch监听(也叫侦听),使用场景和vue2一样,注意他的三个参数和使用格式
8.父子通讯。注意子组件,setup(props,context)第一个参数代表父传子数据,第二个可以context.emit('',XX)进行子传父
9.v-model的语法糖。注意就是名字变了叫 :modelValue和 @update:modelValue事件
10 依赖注入。组件通信,祖宗传后代。祖先组件提供数据provide('数据名1', 数据名)。后代使用数据inject('数据名1')。如果后代想修改数据让祖宗传修改的方法。规则是谁提供的数据谁提供修改的方法