引言
上一章Vue3 ElementPlus Dialog封装 (一:使用props emit)
prop
+emit
实现的方法用于父子组件比较方便, 跨多层次组件比较麻烦
vue3 中 还提供了provide
和inject
方法供组件间通信(参考官网图片), 本篇使用该方法实现上章效果
实现原理
参考官网provide
和inject
例子
官方provide和inject例子
父组件
provide
如下数据
import { ref, provide } from "vue";
const dialogValue = ref({ name: '', email: '', visible: false })
provide('dialogValue', dialogValue)
MyDialog
inject
如下:
import { inject, ref } from 'vue';
const dialogValue = inject('dialogValue')
MyDialog
绑定
如下:
<el-dialog v-model="dialogValue.visible" title="用户录入">
......
<!--
直接绑定dialogValue.name,变化会直接展示到上层组件,
所以里面单独设置个name, email属性,提交适合再改dialogValue中值
-->
<el-input v-model="name" autocomplete="off" />
<el-input v-model="email" autocomplete="off" />
.....
<el-button @click="dialogValue.visible = false">取消</el-button>
<el-button type="primary" @click="handleClick">确认</el-button>
</el-dialog>
<script setup>
import { inject, ref } from 'vue';
const dialogValue = inject('dialogValue')
// 不直接修改dialogValue.name等属性,确定时再提交
const name = ref('')
const email = ref('')
const handleClick = () => {
dialogValue.value.visible = false
dialogValue.value.name = name
dialogValue.value.email = email
}
</scripte>
MyDialog使用如下:
<MyDialog v-model:visible="visible" v-model="dialogValue" />
<!-- 实际省略了默认modelValue, 等同于下 -->
<MyDialog v-model:visible="visible" v-model:modelValue="dialogValue" />
因此组件中需要定义两个prop和emit
const props = defineProps(['visible', 'modelValue'])
const emit = defineEmits(['update:visible', 'update:modelValue'])
emit触发由弹框点击了确认或者关闭按钮适合调用
// 点击取消时候设置visible为false关闭
emit('update:visible', false)
// 点击取消时候设置visible为false关闭,并触发'update:modelValue' 返回结果,更新父组件的v-model值
emit('update:visible', false)
emit('update:modelValue', { name, email })
完整代码
MyDialog.vue
<template>
<el-dialog v-model="dialogValue.visible" title="用户录入">
<el-form>
<el-form-item label="姓名">
<el-input v-model="name" autocomplete="off" />
</el-form-item>
<el-form-item label="邮箱">
<el-input v-model="email" autocomplete="off" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogValue.visible = false">取消</el-button>
<el-button type="primary" @click="handleClick">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { inject, ref } from 'vue';
const dialogValue = inject('dialogValue')
// 不直接修改dialogValue.name等属性,确定时再提交
const name = ref('')
const email = ref('')
const handleClick = () => {
dialogValue.value.visible = false
dialogValue.value.name = name
dialogValue.value.email = email
}
</script>
App.vue
<template>
<el-button type="primary" @click="handleClick">点击获取组件值</el-button>
<MyDialog />
<h1>弹窗结果是: {{ dialogValue }}</h1>
</template>
<script setup>
import { ref, provide } from "vue";
import MyDialog from "~/components/MyDialog.vue";
const dialogValue = ref({ name: '', email: '', visible: false })
provide('dialogValue', dialogValue)
const handleClick = () => {
dialogValue.value.visible = true
}
</script>