美文网首页
Dialog组件

Dialog组件

作者: sweetBoy_9126 | 来源:发表于2020-09-17 17:43 被阅读0次
  • 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)

相关文章