当前位置:首页 > 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 穿梭框树组件实现 穿梭框树组件通常结合了树形结构和穿梭框功能,允许用户在左右两栏之间移动树节点数据。以下是基于 Vue 的实现方案: 核心功能设计 数据结构 树形数据通常采用嵌套结构,例如:…

elementui抽屉

elementui抽屉

elementui抽屉的基本用法 Element UI的抽屉组件(Drawer)是一种从页面边缘滑出的面板,常用于显示额外内容或操作。需要在项目中引入Element UI库后使用。 安装Elemen…

uniapp 分页组件

uniapp 分页组件

uniapp 分页组件实现方法 在uniapp中实现分页功能,可以通过自定义组件或使用第三方组件库完成。以下是几种常见实现方式: 自定义分页组件 创建一个名为uni-pagination的组件,模板…

vue组件实现vmodel

vue组件实现vmodel

Vue 组件实现 v-model 在 Vue 中,v-model 是双向数据绑定的语法糖,默认情况下绑定 value 属性并监听 input 事件。在自定义组件中实现 v-model 需要正确配置 p…

react如何引入组件

react如何引入组件

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

vue组件实现注册

vue组件实现注册

Vue 组件注册的两种方式 全局注册 通过 Vue.component() 方法注册,注册后可在任意 Vue 实例中使用。通常在项目的入口文件(如 main.js)中操作: import V…