当前位置:首页 > VUE

vue实现抽屉组件

2026-02-19 11:19:47VUE

实现基础抽屉组件结构

使用 Vue 的单文件组件方式创建抽屉组件,核心结构包含遮罩层、抽屉主体和内容插槽:

<template>
  <div class="drawer-container">
    <div 
      class="drawer-mask" 
      v-show="visible"
      @click="handleMaskClick">
    </div>

    <div 
      class="drawer-wrapper"
      :class="[placement, { 'visible': visible }]">
      <div class="drawer-content">
        <slot></slot>
      </div>
    </div>
  </div>
</template>

定义组件属性与事件

通过 props 控制抽屉行为,包括显示状态、位置和点击遮罩是否关闭:

vue实现抽屉组件

<script>
export default {
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    placement: {
      type: String,
      default: 'right',
      validator: (value) => ['top', 'right', 'bottom', 'left'].includes(value)
    },
    maskClosable: {
      type: Boolean,
      default: true
    }
  },
  methods: {
    handleMaskClick() {
      if (this.maskClosable) {
        this.$emit('update:visible', false);
      }
    }
  }
}
</script>

添加基础样式

实现抽屉动画效果和不同位置的定位:

<style scoped>
.drawer-container {
  position: relative;
}

.drawer-mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  z-index: 1000;
}

.drawer-wrapper {
  position: fixed;
  z-index: 1001;
  transition: all 0.3s;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.drawer-wrapper.right {
  top: 0;
  right: 0;
  height: 100%;
  transform: translateX(100%);
}

.drawer-wrapper.left {
  top: 0;
  left: 0;
  height: 100%;
  transform: translateX(-100%);
}

.drawer-wrapper.top {
  top: 0;
  left: 0;
  width: 100%;
  transform: translateY(-100%);
}

.drawer-wrapper.bottom {
  bottom: 0;
  left: 0;
  width: 100%;
  transform: translateY(100%);
}

.drawer-wrapper.visible.right,
.drawer-wrapper.visible.left {
  transform: translateX(0);
}

.drawer-wrapper.visible.top,
.drawer-wrapper.visible.bottom {
  transform: translateY(0);
}

.drawer-content {
  width: 100%;
  height: 100%;
  overflow: auto;
}
</style>

添加标题和关闭按钮

增强抽屉组件的功能性,添加标题栏和关闭控制:

vue实现抽屉组件

<template>
  <!-- 原有结构基础上添加 -->
  <div class="drawer-header" v-if="title || showClose">
    <span class="drawer-title">{{ title }}</span>
    <button 
      v-if="showClose"
      class="drawer-close"
      @click="$emit('update:visible', false)">
      ×
    </button>
  </div>
</template>

<script>
export default {
  props: {
    title: String,
    showClose: {
      type: Boolean,
      default: true
    }
    // 其他原有props...
  }
}
</script>

<style scoped>
.drawer-header {
  padding: 16px 24px;
  border-bottom: 1px solid #f0f0f0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.drawer-title {
  font-size: 16px;
  font-weight: 500;
}

.drawer-close {
  font-size: 18px;
  cursor: pointer;
  background: transparent;
  border: none;
}
</style>

控制抽屉宽度/高度

通过 props 允许自定义抽屉尺寸:

props: {
  width: {
    type: [String, Number],
    default: '30%'
  },
  height: {
    type: [String, Number],
    default: '30%'
  }
}
<div 
  class="drawer-wrapper"
  :class="[placement, { 'visible': visible }]"
  :style="placement === 'left' || placement === 'right' 
    ? { width: typeof width === 'number' ? `${width}px` : width }
    : { height: typeof height === 'number' ? `${height}px` : height }">
  <!-- 内容不变 -->
</div>

实现嵌套抽屉支持

修改 z-index 策略避免嵌套抽屉冲突:

data() {
  return {
    zIndex: this.getNextZIndex()
  };
},
methods: {
  getNextZIndex() {
    let zIndex = 1000;
    const drawers = document.querySelectorAll('.drawer-mask');
    if (drawers.length > 0) {
      zIndex = Number(window.getComputedStyle(drawers[drawers.length - 1]).zIndex) + 1;
    }
    return zIndex;
  }
}
<div 
  class="drawer-mask" 
  v-show="visible"
  :style="{ zIndex }"
  @click="handleMaskClick">
</div>

<div 
  class="drawer-wrapper"
  :style="{
    zIndex: zIndex + 1,
    ...placementStyle
  }">
  <!-- 内容不变 -->
</div>

标签: 抽屉组件
分享给朋友:

相关文章

vue如何实现目录组件

vue如何实现目录组件

实现目录组件的基本思路 在Vue中实现目录组件通常需要结合页面内容的结构化数据(如标题层级),通过动态渲染生成可交互的目录。核心步骤包括提取标题、生成目录结构、实现滚动联动等。 提取标题信息 通过d…

uniapp组件写法

uniapp组件写法

Uniapp 组件的基本写法 Uniapp 的组件写法与 Vue 类似,支持单文件组件(.vue 文件)。一个基本的组件通常包含三个部分:<template>、<script>…

vue实现组件

vue实现组件

Vue 实现组件的方法 Vue 中实现组件可以通过多种方式,包括全局注册、局部注册、单文件组件(SFC)等。以下是常见的实现方法。 全局注册组件 全局注册的组件可以在任何 Vue 实例或组件中使用。…

组件elementui

组件elementui

ElementUI 简介 ElementUI 是一套基于 Vue.js 的桌面端组件库,由饿了么前端团队开发并开源。它提供了丰富的 UI 组件(如按钮、表单、表格等),适合快速构建企业级中后台产品。…

vue实现水印组件

vue实现水印组件

Vue 水印组件的实现方法 使用Canvas绘制水印 在Vue组件中通过Canvas动态生成水印图案,将其作为背景添加到目标元素上。 <template> <div ref="…

react如何引入组件

react如何引入组件

引入组件的常见方法 直接导入组件文件 通过import语句从指定路径引入组件文件,适用于项目内自定义组件。假设组件文件位于./components/Button.js: import Button…