Skip to content

Vue3 自定义 Drawer 抽屉组件

本次简单的展示了如何自定义一个 Drawer 抽屉组件

vue
<script lang='ts' setup>
import {ref, reactive, watch} from 'vue'

interface Props {
  visible: boolean
}

const props = withDefaults(defineProps<Props>(), {
  visible: false
})

const emit = defineEmits<{(e: 'update:visible', value: boolean): void}>()

const maskStyle = reactive({
  display: 'none',
  opacity: 0
})

const drawerStyle = reactive({
  transform: 'translateX(100%)'
})

const closeDrawer = () => {
  emit('update:visible', false)
}

watch(() => props.visible, (val) => {
  if (val) {
    maskStyle.display = 'block'
    maskStyle.opacity = 0.5
    drawerStyle.transform = 'translateX(0)'
  } else {
    maskStyle.opacity = 0
    drawerStyle.transform = 'translateX(100%)'
    setTimeout(() => {
      maskStyle.display = 'none'
    }, 1000);
  }
}, {
  immediate: true
})
</script>

<template>
  <View @tap="closeDrawer" class="drawer-background" :style="maskStyle"></View>
  <View class="drawer-container" :style="drawerStyle">
    <slot />
  </View>
</template>

<style>
.drawer-background {
  position: fixed;
  top: 0;
  right: 0;
  width: 100%;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.5);
  transition-duration: 0.3s;
  z-index: 1000;
}
.drawer-container {
  position: fixed;
  top: 0;
  right: 0;
  width: 60%;
  height: 100vh;
  background-color: #fff;
  transition-duration: 0.3s;
  transform: translateX(100%);
  z-index: 1000;
}
</style>

上述代码是 taro 的小程序代码实现,主要是通过 transition-duration 来实现动画效果,通过 transform 来实现移动效果,通过 opacity 来实现透明度效果。

需要注意的是通过 transform: translateX(100%); 将抽屉组件移动到屏幕外,通过 transform: translateX(0); 将抽屉组件移动到屏幕内。

蒙版的动画不能立即使用 display: none; 来隐藏,需要通过 setTimeout 来实现,否则动画效果会没效果。

调用

vue
<script lang='ts' setup>
import { ref } from 'vue'
// 是否显示抽屉
const show = ref(false)
function open() {
  show.value = true
}
</script>

<template>
  <Drawer v-model:visible="show">
    drawer content
  </Drawer>
</template>

<style>
</style>