组合式API - 生命周期函数
1. 选项式对比组合式
理解:
在组合式API中没有beforeCreate/create这两构造函数, 可以将原本的内容填入setup中
2. 生命周期函数基本使用
具体操作:
1.导入生命周期函数
2.执行生命周期函数,传入回调
<scirpt setup> import { onMounted } from 'vue' onMounted(()=>{ // 自定义逻辑 }) </script>
**效果:**直接挂载并输出内容
3. 执行多次
作用:生命周期函数执行多次的时候,会按照顺序依次执行
案例:
<scirpt setup> import { onMounted } from 'vue' onMounted(()=>{ // 自定义逻辑 }) onMounted(()=>{ // 自定义逻辑 }) </script>
效果:
如果遇到需要添加需求,我们又不想直接修改他人代码,
我们可以在下面在补充一个onMounted(),里面填写需要的补充逻辑。
总结:
1.组合式API中生命周期函数的格式是什么?
on+生命周期名字
2.组合式AP1中可以使用oncreated吗?
没有这个钩子西数,直接写到setup中
3.组合式AP1中组件卸载完毕时执行哪个函数?
onUnmounted
组合式API - 父子通信
1. 父传子
基本思想:
父组件中给子组件绑定属性
子组件内部通过props选项接收数据
具体操作:
父组件:绑定属性
子组件:通过 defineProps ( 编译器宏函数) 接收子组件传递的数据
案例:
补充:这里添加了响应式数据的父传子的方式,即需要在组件中的属性前加上:
App.vue
<template> <div class="father"> <h2>父组件App</h2> <!-- 1. 绑定属性 --> <son-com :count="count" message="father message"></son-com> </div> </template> <script setup> import { ref } from 'vue' // setup语法糖下局部组件无需注册直接可以使用 import SonCom from './components/son.vue' const count = ref(100) </script>
son.vue
<template> <div class="son"> <h3>子组件Son</h3> <div> 父组件传入的数据 - {{ message }} - {{ count }} </div> </div> </template> <script setup> //2. defineProps接收数据 defineProps({ message: String, count: Number, }) </script>
效果:
拓展理解:关于编译器宏函数
我们将代码放到Vue SFC Playground中,可以发现defineProps实际上是个标志,当代码编译时,会把左边的代码编译成右边我们熟悉的代码。
2. 子传父
基本思想:
1.父组件中给子组件标签通过@绑定事件 2. 子组件内部通过 emit 方法触发事件
具体操作:
1.父组件绑定自定义事件
2.通过defineEmits编译器宏生成emit方法
3.触发自定义事件,并传递参数
总结:
父传子
1.父传子的过程中通过什么方式接收props?
defineProps({属性名:类型})
2.setup语法糖中如何使用父组件传过来的数据?
const props =defineProps( {属性名:类型})
子传父
1.子传父的过程中通过什么方式得到emit方法?
defineEmits(['事件名称’])
组合式API - 模版引用 (这一块需要再看看)
概念:通过 ref标识 获取真实的 dom对象或者组件实例对象
1. 基本使用
实现步骤: 1. 调用ref函数生成一个ref对象 2. 通过ref标识绑定ref对象到标签
代码演示:
<script setup> // 1. 调用ref函数 -> ref对象 const h1Ref = ref(null) </script> <template> <!-- 2. 通过ref标识绑定ref对象 --> <h1 ref="h1Ref">我是dom标签</h1> </template>
理解:通过1和2两步,dom对象已经被存到了h1Ref.value身上
案例:
如果我们想要获取数据(比如h1.value),需要等到组件挂载完毕之后才能获取
<template> <!-- 2. 通过ref标识绑定ref对象 --> <h1 ref="h1Ref">我是dom标签1</h1> <test-com></test-com> </template> <script setup> import { onMounted, ref } from 'vue' import TestCom from './components/son.vue' // 1. 调用ref函数 -> ref对象 const h1Ref = ref(null) const comRef = ref(null) // 组件挂载完毕之后才能获取 onMounted(() => { console.log(h1Ref.value) console.log(TestCom.value) }) </script>
2. defineExpose
默认情况下在
说明:指定testMessage属性可以被访问到
总结:
1.获取模板引用的时机是什么?
组件挂载完毕
2.defineExpose编译宏的作用是什么?
显式暴露组件内部的属性和方法
组合式API - provide和inject
1. 作用和场景
顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信
理解:room-page称为顶层组件,room-msg-comment称为底层组件
2. 跨层传递普通数据
实现步骤:
1.顶层组件通过 provide 函数提供数据
2.底层组件通过 inject 函数提供数据
顶层组件:
provide('key', 顶层组件中的数据)
底层组件:
const message = inject('key')
注意:以上二者的key相互关联
案例:
效果:
3. 跨层传递响应式数据
具体操作:在调用provide函数时,第二个参数设置为ref对象
顶层组件:
provide('app-key', ref对象)
底层组件:
const message = inject('app-key')
案例:
效果:
4. 跨层传递方法
逻辑:顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件的数据
顶层组件:
const setCount = () => { count.value++ } provide('setCount-key', setCount)
底层组件:
const setCount = inject('setCount-key')
案例:
效果:点击按钮,顶层组件的响应式数据会变化
总结:
需求1: 我们需要从顶层传递订单id等信息到底层组件
顶层提供provide(’id-key’, orderId),底层采用 inject(’id-key’) 接收,从而实现顶层数据向底层的传递。
需求2: 底层通知顶层评价完毕
顶层提供provide(’state-fn’, changeState)传递函数, 底层通过inject(’state-fn’) → changeState()接收函数并调用,从而实现对顶层数据的修改
Q&A:
1.provide和inject的作用是什么?
跨层组件通信
2.如何在传递的过程中保持数据响应式?
第二个参数传递ref对象
3.底层组件想要通知顶层组件做修改,如何做?
传递方法,底层组件调用方法
4.一颗组件树中只有一个顶层或底层组件吗?
相对概念,存在多个顶层和底层的关系
综合案例
案例演示:
1. 项目地址
git clone http://git.itcast.cn/heimaqianduan/vue3-basic-project.git
2. 项目说明
1.模版已经配置好了案例必须的安装包
2.案例用到的接口在 README.MD文件 中
3.案例项目有俩个分支,main主分支为开发分支,complete分支为完成版分支供开发完参考
3. 项目实现:
步骤1: 列表渲染
效果:
实现:
// TODO1: 列表渲染 // 思路:声明响应式list -> 调用接口获取数据 -> 后端数据赋值给list -> 绑定到table组件 // 具体步骤: const list = ref([]) // 1.调用发送的异步请求 const getList = async () => { // 接口调用 const res = await axios.get('/list') // 交给list list.value = res.data } onMounted( () => getList())
说明:我们将数据传输给相应的列表
步骤2: 删除功能
效果:
实现:
// TODO: 删除功能 // 思路:获取当前行的id -> 通过id调用删除接口 -> 更新最新的列表 const onDelete = async (id) => { console.log(id); await axios.delete(`/del/${id}`) getList() }
说明:
步骤3: 编辑功能
效果:
实现:
主组件:
// TODO: 编辑功能 // 思路:打开弹窗 -> 回填数据 -> 更新数据 // 1. 打开弹窗 (获取子组件实例 调用方法或者修改属性) const editRef = ref(null) const onEdit = (row) => { editRef.value.open(row) } // 2. 回调数据 (调用详情接口 / 当前行的静态数据)
编辑功能组件:
<script setup> // TODO: 编辑 import { ref } from 'vue' import axios from 'axios'; // 弹框开关 const dialogVisible = ref(false) // 准备form const form = ref({ name: '', place: '', id: '' }) const open = (row) => { console.log(row) form.value.name = row.name form.value.place = row.place form.value.id = row.id dialogVisible.value = true } defineExpose({ open }) // 更新 const emit = defineEmits(['on-update']) const onUpdata = async () => { // 1. 收集表单数据,调用接口 await axios.patch(`/edit/${form.value.id}`, { name: form.value.name, place: form.value.place, }) // 2. 关闭弹窗 dialogVisible.value = false // 3. 通知父组件做列表更新 emit('on-update') } </script> <template> <el-dialog v-model="dialogVisible" title="编辑" width="400px"> <el-form label-width="50px"> <el-form-item label="姓名"> <el-input placeholder="请输入姓名" v-model="form.name"/> </el-form-item> <el-form-item label="籍贯"> <el-input placeholder="请输入籍贯" v-model="form.place"/> </el-form-item> </el-form> <template #footer> <span class="dialog-footer"> <el-button @click="dialogVisible = false">取消</el-button> <el-button type="primary" @click="onUpdata">确认</el-button> </span> </template> </el-dialog> </template>






















