vue自定义抽屉组件

<template>
  <div class="drawer">
    <div :class="maskClass" @click="closeByMask"></div>
    <div :class="mainClass" :style="mainStyle" class="main">
      <div class="drawer-head">
        <span>{{ title }}</span>
        <span
          v-show="closable"
          class="close-btn"
          @click="closeByButton"
        >x</span>
      </div>
      <div class="drawer-body" :style="bodyStyle">
        <slot />
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'drawer',
  props: {
    // 是否打开
    display: {
      type: Boolean
    },
    // 标题
    title: {
      type: String,
      default: '标题'
    },
    // 是否显示关闭按钮
    closable: {
      type: Boolean,
      default: true
    },
    // 是否显示遮罩
    mask: {
      type: Boolean,
      default: true
    },
    // 是否点击遮罩关闭
    maskClosable: {
      type: Boolean,
      default: true
    },
    // 宽度
     {
      type: String,
      default: '400px'
    },
    // 高度
    height: {
      type: String,
      default: '75%'
    },
    // 是否在父级元素中打开
    inner: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    maskClass: function () {
      return {
        'mask-show': this.mask && this.display,
        'mask-hide': !(this.mask && this.display),
        inner: this.inner
      }
    },
    mainClass: function () {
      return {
        'main-show': this.display,
        'main-hide': !this.display,
        inner: this.inner
      }
    },
    mainStyle: function () {
      return {
         this.width,
        height: this.height,
        bottom: this.display ? '0' : `-${this.height}`,
        borderTop: this.mask ? 'none' : '1px solid #eee'
      }
    },
    bodyStyle: function () {
      return {
        height: this.height
      }
    }
  },
  mounted () {
    if (this.inner) {
      let box = this.$el.parentNode
      box.style.position = 'relative'
    }
  },
  methods: {
    closeByMask () {
      this.maskClosable && this.$emit('update:display', false)
    },
    closeByButton () {
      this.$emit('update:display', false)
    }
  }
}
</script>
<style lang="less" scoped>
  .drawer {
    .mask-show {
      position: fixed;
      top: 0;
      left: 0;
       100%;
      height: 100%;
      z-index: 10;
      background-color: rgba(0, 0, 0, 0.5);
      opacity: 1;
      transition: opacity 0.5s;
    }
    .mask-hide {
      opacity: 0;
      transition: opacity 0.5s;
    }
    .main {
      position: fixed;
      z-index: 10;
      bottom: 0;
      height: 100%;
      border-top-left-radius: 10px;
      border-top-right-radius: 10px;
      background: #f7f7f7;
      transition: all 0.5s;
    }
    .main-show {
      opacity: 1;
    }
    .main-hide {
      opacity: 0;
    }
    .inner {
      position: absolute;
    }
    .drawer-head {
      display: flex;
      justify-content: space-between;
      align-items: center;
      height: 50px;
      padding: 20px;
      box-sizing: border-box;
      border-top-left-radius: 10px;
      border-top-right-radius: 10px;
      font-size: 16px;
      font-weight: bold;
      background: #fff;
      position: relative;
      border-bottom: 1px solid #eee;
      .close-btn {
        font-size: 24px;
        position: absolute;
        right: 20px;
        top: 50%;
        transform: translateY(-50%);
        display: inline-block;
        cursor: pointer;
      }
    }
    .drawer-body {
      // padding: 20px;
      font-size: 14px;
      overflow: auto;
    }
  }
</style>
import drawer from './drawer'



  components: { drawer },



      display: true,
      drawerWidth: '100%',
      drawerHeight: '500px',












    <el-button type="primary" @click="display = !display">{{display?'close': 'open'}}</el-button>
    <drawer title="我是标题" :display.sync="display" :width="drawerWidth" :height="drawerHeight">
      <div>123</div>
    </drawer>

cnpm install stylus-loader css-loader style-loader --save-dev

cnpm install less less-loader --save-dev

第二种方案:

<template>
  <div class="drawer">
    <button @click="clickBtn">点击</button>

    <div class="background" v-if="open" @click.self="closeDrop">
      <div class="drop" :class="{ active: isActive, close: isClose }">drop</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {},
  data () {
    return {
      open: false,
      isActive: false,
      isClose: false
    }
  },
  methods: {
    clickBtn () {
      this.open = true
      this.isActive = true
      this.isClose = false
    },
    closeDrop () {
      this.isClose = true
      setTimeout(() => {
        this.open = false
      }, 200)
    }
  }
}
</script>

<style scoped lang="scss">
  .background {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background: rgba($color: #000000, $alpha: 0.5);
    .drop {
       0px;
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      background: #fff;
    }
    //
    .active {
      animation: opendoor 0.3s normal forwards;
    }
    @keyframes opendoor {
      from {
         0;
      }
      to {
         45%;
      }
    }
    //
    .close {
      animation: close 0.3s normal forwards;
    }
    @keyframes close {
      0% {
         45%;
      }
      100% {
         0;
        opacity: 0;
      }
    }
  }
</style>
原文地址:https://www.cnblogs.com/scode2/p/11360121.html