赞
踩
前几天被人问到过,当时挺懵的,回来看了看,发现原来是这样做的
效果图如下,只实现了一个最基本的,可以传入属性,也可以使用方法,后续需要什么,再往里面加
主要是通过v-model控制对话框的显示和隐藏,实现父子组件的双向数据绑定
父组件
- <template>
- <div class="dialog">
- <button @click.stop="showModel">显示对话框 -- {{ show }}</button>
- <Diglog
- v-model="show"
- :title="title"
- @open="handleOpen"
- @close="handleClose"
- >
- <p>插槽内容</p>
- <template #footer>
- <span>
- <button @click="show = false">确定</button>
- <button @click="show = false">取消</button>
- </span>
- </template>
- </Diglog>
- </div>
- </template>
-
- <script setup>
- import { ref } from 'vue'
- import Diglog from './components/Diglog.vue'
- // 控制对话框显示/隐藏
- let show = ref(false)
- // 窗口标题
- let title = ref('标题呀')
-
- const showModel = () => {
- show.value = true
- }
-
- const handleOpen = (a) => {
- console.log('打开了' + '默认参数为' + a)
- }
-
- const handleClose = (a) => {
- console.log('关闭了' + '默认参数为' + a)
- }
- </script>
子组件
- <template>
- <div class="box" ref="box" v-show="props.modelValue">
- <i class="close" @click="closeModel">X</i>
- <h3 class="title">{{ props.title }}</h3>
- <slot>插槽备用内容1</slot>
- <footer class="footer">
- <slot name="footer">插槽备用内容2</slot>
- </footer>
- </div>
- </template>
-
- <script setup>
- import { defineProps, defineEmits, ref, watch } from 'vue'
-
- const props = defineProps({
- modelValue: {
- type: Boolean,
- default: false,
- },
- title: {
- type: String,
- default: '',
- },
- })
-
- let box = ref(null)
-
- const emits = defineEmits(['update:modelValue', 'open', 'close'])
-
- document.addEventListener('click', function (e) {
- if (!box.value.contains(e.target)) {
- emits('update:modelValue', false)
- }
- })
-
- const closeModel = () => {
- emits('update:modelValue', false)
- }
-
- watch(
- // 这种写法会侦听到 props 中 test 的变化
- () => props.modelValue,
- (newValue) => {
- // 打开了
- if (newValue === true) {
- emits('open', '随便传个参数吧1')
- }
- // 关闭了
- if (newValue === false) {
- emits('close', '随便传个参数吧2')
- }
- }
- )
- </script>
-
- <style scoped>
- .box {
- position: relative;
- width: 500px;
- height: 300px;
- background-color: pink;
- margin: auto;
- }
-
- .title {
- text-align: center;
- height: 30px;
- background: skyblue;
- }
-
- .close {
- display: block;
- position: absolute;
- top: 0;
- right: 0;
- width: 30px;
- text-align: center;
- line-height: 30px;
- background-color: #ccc;
- cursor: pointer;
- }
-
- .footer {
- position: absolute;
- bottom: 0;
- right: 0;
- }
- </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。