- Dialog.vue
<template>
<Teleport to="body">
<template v-if="visible">
<div class="ivue3-dialog-overlay"
@click="onClickOverlay"
></div>
<div class="ivue3-dialog-wrapper">
<div class="ivue3-dialog">
<header>
<slot name="title"/>
<span @click="onClose" class="ivue3-dialog-close"></span>
</header>
<main>
<slot name="content"/>
</main>
<footer>
<Button level="main" @click="ok">OK</Button>
<Button @click="cancel">Cancel</Button>
</footer>
</div>
</div>
</template>
</Teleport>
</template>
<script lang="ts">
import Button from './Button.vue'
import {ref, SetupContext} from "vue";
export default {
components: {Button},
props: {
visible: {
type: Boolean,
default: false
},
closeOnClickOverlay: {
type: Boolean,
default: true
},
ok: {
type: Function
}
},
setup(props: any, context: SetupContext) {
const test = ref
const onClose = () => {
context.emit('update:visible', !props.visible)
}
const onClickOverlay = () => {
if (props.closeOnClickOverlay) {
onClose()
}
}
const ok = () => {
if (props.ok?.() !== false) {
onClose()
}
}
const cancel = () => {
context.emit('cancel')
onClose()
}
return {onClose, onClickOverlay, ok, cancel}
}
}
</script>
- DialogDemo.vue
<template>
<div>
<div>Dialog示例</div>
<h1>示例1</h1>
<Button @click="onClickToggle">Dialog</Button>
<Dialog v-model:visible="x" :ok="f1" @cancel="f2" title="我美吗">
<template v-slot:title>
<h1>哈哈哈</h1>
</template>
<template v-slot:content>
<p>你好呀</p>
<p>小姐姐</p>
</template>
</Dialog>
</div>
</template>
<script lang="ts">
import Dialog from '../lib/Dialog.vue'
import Button from '../lib/Button.vue'
import {ref} from "vue";
export default {
name: 'Switch',
components: {Dialog, Button},
setup() {
const x = ref(false)
const onClickToggle = () => {
x.value = !x.value
}
const f1 = (): Boolean => {
return false
}
const f2 = (): Boolean => {
return true
}
return {x, onClickToggle, f1, f2}
}
}
</script>
我们希望直接使用下面的一行代码就可以打开我们的Dialog
<Button @click="showDialog">show</Button>
const showDialog = () => {
openDialog({title: '标题', content: '你好'})
}
单独 创建一个openDialog.ts文件导出openDialog方法
- openDialog.ts
import Dialog from './Dialog.vue'
import {createApp} from 'vue'
interface Options {
title: string;
content: string;
}
export const openDialog = (options: Options) => {
const {title, content} = options
// 因为我们需要将我们的Dialog挂载到页面上所以我们需要创建一个div
const div = document.createElement('div')
document.body.append(div)
const app = createApp(Dialog)
// 将Dialog组件挂载到div下面
app.mount(div)
}
问题1:上面的代码我们点击按钮的时候发现Dialog并没有出来,但是我们看控制台里的html里我们新添加的div标签已经添加到了body下面
原因:因为我们的Dialog组件需要传入一个visible属性,你不传它默认就是false,所以不会显示
解决方法:通过引入h函数第一个参数是组件,第二个是元素的属性(第一个参数组件的props,也就是直接可以在使用组件的时候传入的属性),第三个是插槽的属性
- openDialog.ts
import {createApp, h} from 'vue'
const app = createApp({
render() {
return h(Dialog, {visible: true, cancel: () => {}}, {title, content})
}
})
问题2:我们通过上面的代码打开的Dialog点击关闭关闭不了
原因:我们在把visible作为属性传入的时候我们把它给写死了等于true了
解决方法:关闭的时候直接把我们创建的Dialog销毁就好了,就不需要改visible了,也就是我们监听我们的update:visible
事件当它变为false的时候就把我们的Dialog销毁掉,这里要注意我们在render里监听我们的update事件需要写成onUpdate:对应的属性名
,比如onUpdate:visible
const app = createApp({
render() {
return h(Dialog, {
visible: true, cancel: () => {},
'onUpdate:visible': (newValue: boolean) => {
if (newValue === false) {
app.unmount(div)
}
}
}, {title, content})
}
})
app.mount(div)
网友评论