当前位置:首页 > VUE

vue实现dialog窗口

2026-03-08 04:50:16VUE

使用 Vue 实现 Dialog 窗口

基础 Dialog 组件实现

创建一个名为 Dialog.vue 的组件文件,包含基本的对话框结构:

<template>
  <div class="dialog-overlay" v-if="visible" @click.self="close">
    <div class="dialog-content">
      <div class="dialog-header">
        <slot name="header">
          <h3>{{ title }}</h3>
        </slot>
        <button @click="close">×</button>
      </div>
      <div class="dialog-body">
        <slot></slot>
      </div>
      <div class="dialog-footer">
        <slot name="footer">
          <button @click="close">取消</button>
          <button @click="confirm">确认</button>
        </slot>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    visible: Boolean,
    title: {
      type: String,
      default: '提示'
    }
  },
  methods: {
    close() {
      this.$emit('update:visible', false)
    },
    confirm() {
      this.$emit('confirm')
      this.close()
    }
  }
}
</script>

<style scoped>
.dialog-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.dialog-content {
  background: white;
  border-radius: 4px;
  min-width: 300px;
  max-width: 80%;
}

.dialog-header {
  padding: 16px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #eee;
}

.dialog-body {
  padding: 16px;
}

.dialog-footer {
  padding: 16px;
  text-align: right;
  border-top: 1px solid #eee;
}
</style>

在父组件中使用 Dialog

<template>
  <div>
    <button @click="showDialog = true">打开对话框</button>
    <Dialog
      v-model:visible="showDialog"
      title="自定义标题"
      @confirm="handleConfirm"
    >
      <template #header>
        <h3>自定义头部</h3>
      </template>

      <p>这是对话框的内容区域</p>

      <template #footer>
        <button @click="showDialog = false">关闭</button>
        <button @click="submitForm">提交</button>
      </template>
    </Dialog>
  </div>
</template>

<script>
import Dialog from './Dialog.vue'

export default {
  components: { Dialog },
  data() {
    return {
      showDialog: false
    }
  },
  methods: {
    handleConfirm() {
      console.log('确认操作')
    },
    submitForm() {
      console.log('提交表单')
      this.showDialog = false
    }
  }
}
</script>

全局 Dialog 服务实现

创建全局可调用的 Dialog 服务:

  1. 创建 dialog.js 服务文件:
import Vue from 'vue'

const DialogConstructor = Vue.extend(require('./Dialog.vue').default)

let dialogInstance = null

const Dialog = function(options) {
  if (dialogInstance) {
    dialogInstance.visible = false
  }

  dialogInstance = new DialogConstructor({
    el: document.createElement('div'),
    propsData: options
  })

  document.body.appendChild(dialogInstance.$el)

  return new Promise((resolve, reject) => {
    dialogInstance.$on('confirm', () => {
      resolve()
    })
    dialogInstance.$on('update:visible', (val) => {
      if (!val) {
        reject(new Error('Dialog closed'))
      }
    })

    Vue.nextTick(() => {
      dialogInstance.visible = true
    })
  })
}

Dialog.install = function(Vue) {
  Vue.prototype.$dialog = Dialog
}

export default Dialog
  1. 在 main.js 中注册:
import Dialog from './services/dialog'

Vue.use(Dialog)
  1. 在组件中使用全局 Dialog:
this.$dialog({
  title: '全局对话框',
  content: '这是通过服务调用的对话框'
}).then(() => {
  console.log('确认操作')
}).catch(() => {
  console.log('取消操作')
})

动画效果增强

为 Dialog 添加过渡动画:

<template>
  <transition name="dialog-fade">
    <div class="dialog-overlay" v-if="visible" @click.self="close">
      <transition name="dialog-slide">
        <div class="dialog-content">
          <!-- 原有内容 -->
        </div>
      </transition>
    </div>
  </transition>
</template>

<style scoped>
.dialog-fade-enter-active,
.dialog-fade-leave-active {
  transition: opacity 0.3s;
}

.dialog-fade-enter,
.dialog-fade-leave-to {
  opacity: 0;
}

.dialog-slide-enter-active,
.dialog-slide-leave-active {
  transition: transform 0.3s;
}

.dialog-slide-enter,
.dialog-slide-leave-to {
  transform: translateY(-20px);
}
</style>

可拖动 Dialog 实现

添加拖动功能:

vue实现dialog窗口

// 在 Dialog.vue 的 script 部分添加
data() {
  return {
    dragData: {
      isDragging: false,
      startX: 0,
      startY: 0,
      startLeft: 0,
      startTop: 0
    }
  }
},
methods: {
  startDrag(e) {
    this.dragData.isDragging = true
    this.dragData.startX = e.clientX
    this.dragData.startY = e.clientY
    const rect = this.$el.getBoundingClientRect()
    this.dragData.startLeft = rect.left
    this.dragData.startTop = rect.top
    document.addEventListener('mousemove', this.onDrag)
    document.addEventListener('mouseup', this.stopDrag)
  },
  onDrag(e) {
    if (!this.dragData.isDragging) return
    const dx = e.clientX - this.dragData.startX
    const dy = e.clientY - this.dragData.startY
    this.$el.style.left = `${this.dragData.startLeft + dx}px`
    this.$el.style.top = `${this.dragData.startTop + dy}px`
  },
  stopDrag() {
    this.dragData.isDragging = false
    document.removeEventListener('mousemove', this.onDrag)
    document.removeEventListener('mouseup', this.stopDrag)
  }
}
<!-- 修改 dialog-header 部分 -->
<div class="dialog-header" @mousedown="startDrag">
  <!-- 原有内容 -->
</div>
/* 修改 dialog-overlay 样式 */
.dialog-overlay {
  /* 移除 justify-content 和 align-items */
  /* 添加 position: relative */
}

.dialog-content {
  position: absolute;
}

标签: 窗口vue
分享给朋友:

相关文章

实现vue模版

实现vue模版

Vue 模板的基本结构 Vue 模板基于 HTML 语法,通过 Vue 的指令和插值实现动态渲染。以下是一个基础模板示例: <template> <div id="app"…

vue实现选区

vue实现选区

Vue 实现选区的基本方法 在Vue中实现选区功能通常涉及DOM操作和事件处理。以下是几种常见的方法: 使用原生JavaScript的Selection API 通过window.getSelec…

vue实现分类

vue实现分类

Vue实现分类功能的方法 使用v-for和计算属性 通过计算属性对数据进行分类处理,结合v-for渲染分类后的列表。示例代码: <template> <div>…

vue实现tag

vue实现tag

Vue 实现标签(Tag)功能 在 Vue 中实现标签(Tag)功能可以通过多种方式完成,以下是一些常见的方法和实现步骤: 使用动态组件和 v-for 通过 v-for 指令动态渲染标签列表,结合样…

vue实现公式

vue实现公式

在Vue中实现公式展示或计算可以通过多种方式实现,以下为具体方法: 使用模板插值与计算属性 若公式较简单,可直接在模板中使用插值表达式或计算属性。例如计算圆的面积: <template>…

vue 实现全屏

vue 实现全屏

Vue 实现全屏功能 在 Vue 中实现全屏功能可以通过浏览器提供的 Fullscreen API 完成。以下是一个完整的实现方案: 安装依赖(可选) 如果需要跨浏览器兼容性更好,可以安装 scre…