vue3 父子组件传参,provide/inject 共享方法和参数,父组件调用子组件方法,子组件调用父组件方法
一、父组件给子组件传参 props
props
用法 vue props:{ xxxx: { type: Object, default:null } }
以下有注释的部分是需要写的代码
以下例子是父组件(列表页)加载公共的操作按钮
子组件.vue
以设置权限为例
<template> <vab-query-form-left-panel :span="12"> <el-button :disabled="buttonDis.disPerssion" icon="el-icon-plus" type="primary" @click="showSetPermission" > 设置权限 </el-button> </vab-query-form-left-panel> </template> <script> import { ref, toRefs, reactive } from 'vue' export default { name: 'FunctionArea', // 定义父组件 html 传参时的 key 名字 // 在父组件中 listData 的写法变为 list-data props: { listData: { type: Object, default: null } }, setup(props) { const state = reactive({ // 将从父组件中获取的 listData 的值付给新的变量 // 通过 props 调用 buttonDis: props.listData, }) return { ...toRefs(state), } }, } </script>
父组件.vue
<template> <div class="user-management-container"> <vab-query-form> <!-- 这里 :list-data 给子组件传参数 --> <FunctionArea :list-data="buttonDis" /> </vab-query-form> <Paging ref="pagging" /> </div> </template> <script> import { defineComponent, reactive, toRefs, provide } from 'vue' // 加载组件 import FunctionArea from '../functionArea/functionArea' export default defineComponent({ name: 'List', // 注册组件 components: { FunctionArea }, setup() { const selectRows = reactive({ list: {}, }) // 按钮是否禁用的状态,把这个传给子组件 const buttonDis = reactive({ disDelete: true, disEdit: true, disPerssion: true, }) const setSelectRows = (val) => { selectRows.list = val if (selectRows.list.length === 1) { buttonDis.disEdit = false buttonDis.disDelete = false buttonDis.disPerssion = false } else if (selectRows.list.length != 1) { buttonDis.disEdit = true buttonDis.disDelete = false buttonDis.disPerssion = true } } const fetchData = async () => { const { data } = await getList() } onMounted(() => { fetchData() }) return { ...toRefs(state), // 把要传给子组件的参数,返回到模板中 buttonDis, } }, }) </script>
二、父组件调用子组件方法
关键步骤都在父组件中。
在 html 中加载组件 html,然后在 html 中添加 ref='xxx'
获取子组件对象 const xxx = ref(null)
在父组件的 return 中返回 xxx
:这里的 xxx 都是相同的名字
子组件.vue
<template> <div id="AdminEdit"> <el-dialog v-model="dialogFormVisible" :title="title" width="600px" @close="close"> <template #footer> <el-button @click="close">取消</el-button> <el-button type="primary" @click="save">确定</el-button> </template> </el-dialog> </div> </template> <script> import { defineComponent, reactive } from 'vue' export default defineComponent({ name: 'AdminEdit', setup() { const state = reactive({ formRef: null, dialogFormVisible: false, }) // 这个是父组件要调用的方法 const showEdit = () => { state.dialogFormVisible = true } const close = () => {} const save = () => {} return { ...toRefs(state), // 这里要返回 showEdit, close, save, } }, }) </script>
父组件.vue
父组件调用子组件的显示弹框方法 howEdit
<template> <!-- html 加载子组件,并定义 ref --> <AdminEdit ref="editRef" /> </template> <script> import { ref, toRefs, reactive } from 'vue' // 加载组件 import AdminEdit from '../operation/setEidt/AdminEdit' export default { name: 'FunctionArea', // 注册子组件 components: { AdminEdit }, setup(props) { // 声明子组件对象 // 注意,注意:这里的 editRef 与上面 html中 ref 值相同 const editRef = ref(null) const showEdit = () => { // 通过 editRef.value 调用子组件中的方法 editRef.value.showEdit() } return { showEdit, // 注意,注意: 这个editRef 一定要 return 出去 editRef, } }, } </script>
三、provide/inject 父组件跨子组件共享传参和方法
父组件中定义 provide,发送参数
子组件中定义 inject,获取参数
这里碰到一个问题,provide 发送的数组对象 inject 接收后都是 proxy 类型的,需要 toRaw 将其转移才能调用。有别的好办法请留言谢谢~~~
父组件.vue
<template> </template> <script> import { defineComponent, provide, reactive } from 'vue' export default defineComponent({ name: 'List', setup() { const selectRows = reactive({ list: {}, }) // 发送 selectRows 中数据到全局子组件中 provide('selectRows', selectRows) const refreshData = () => { ........ } // 共享方法 也是可以的 provide('refreshData', refreshData) return {} }, }) </script>
子组件.vue
<template> </template> <script> import { defineComponent, reactive, inject } from 'vue' export default defineComponent({ name: 'Perssion', setup() { // 这里获取 selectRows 的数据 // 这里获取的是 proxy 类型的数据,需要toRaw转化为数组 const row = toRaw(inject('selectRows')) const refreshData = inject('refreshData') onMounted(() => { // 调用共享的方法 refreshData() }) } }) </script>
四、子组件调用父组件方法 emits
子组件调用父组件方法,实际上是子组件调用父组件传入子组件的方法。
子组件.vue
<template> </template> <script> import { defineComponent } from 'vue' export default defineComponent({ name: 'Perssion', // 设置需要父组件传入方法的 key emits: ['refreshList'], // 这里需要给 setup 定义两个参数,第二个 { emit } 是调用父组件方法的方法 setup(props, { emit }) { onMounted(() => { // 调用父组件传入的方法,val 是可以给方法传参(可不传) emit('refreshList', val) }) } }) </script>
父组件.vue
<template> <!-- 这里的 @refreshList 就是在子组件 emits 中设置的 key --> <!-- @refreshList 里面是传入需要被子组件调用的方法 --> <Perssion @refreshList="refreshList" /> </template> <script> import { defineComponent } from 'vue' // 加载组件 import Perssion from '../perssion' export default defineComponent({ name: 'List', components: { Perssion }, setup() { // 定义父组件方法 const refreshList = (val) => { ....... } return { refreshList, } }, }) </script>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)