el-drawer 学习笔记

3,582 阅读1分钟

动态绑定class写法

:class="visible && 'el-drawer__open'"
:class="[direction, customClass]"

props: {
    direction: {
      type: String,
      default: 'rtl',
      validator(val) {
        return ['ltr', 'rtl', 'ttb', 'btt'].indexOf(val) !== -1;
      }
    }
}

动态绑定样式

:style="isHorizontal ? `width: ${size}` : `height: ${size}`"

props: {
    size: {
      type: String,
      default: '30%'
    },
}

传参校验

direction: {
  type: String,
  default: 'rtl',
  validator(val) {
    return ['ltr', 'rtl', 'ttb', 'btt'].indexOf(val) !== -1;
  }
},

watch visible

watch: {
visible(val) {
  if (val) {
    this.closed = false;
    this.$emit('open');
    if (this.appendToBody) {
      document.body.appendChild(this.$el);
    }
    // 保存focus elment, 注意更新focus和关闭时重置focus都用nextTick
    this.prevActiveElement = document.activeElement;
    this.$nextTick(() => {
      Utils.focusFirstDescendant(this.$refs.drawer);
    });
  } else {
    if (!this.closed) this.$emit('close');
    this.$nextTick(() => {
      if (this.prevActiveElement) {
        this.prevActiveElement.focus();
      }
    });
  }
}
},

类型校验

typeof this.beforeClose === 'function'

destroyed

destroyOnClose 只是让不再渲染,只有搭配 appendToBody 才能真正实现关闭即销毁。 ? 实践后发现也不行,哭泣。。。,只能老老实实的 reset 了

destroyed() {
// if appendToBody is true, remove DOM node after destroy
if (this.appendToBody && this.$el && this.$el.parentNode) {
  this.$el.parentNode.removeChild(this.$el);
}
}

transition 动画

  • 透明度的动画:el-drawer-fade
<transition
    name="el-drawer-fade" //定义 name
</transition>

// 定义 关键帧
@keyframes el-drawer-fade-in {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
// 过渡钩子
.el-drawer-fade-enter-active {
  animation: el-drawer-fade-in .3s;
}

.el-drawer-fade-leave-active {
  animation: el-drawer-fade-in .3s reverse;
}

  • 打开关闭的动画
$directions: rtl, ltr, ttb, btt;

// 声明定义关键帧
@mixin drawer-animation($direction) {

  // 声明 drawer-in 关键帧
  @keyframes #{$direction}-drawer-in {
    0% {

      @if $direction == ltr {
        transform: translate(-100%, 0px);
      }

      @if $direction == rtl {
        transform: translate(100%, 0px);
      }

      @if $direction == ttb {
        transform: translate(0px, -100%);
      }

      @if $direction == btt {
        transform: translate(0px, 100%);
      }
    }

    100% {
      @if $direction == ltr {
        transform: translate(0px, 0px);
      }

      @if $direction == rtl {
        transform: translate(0px, 0px);
      }

      @if $direction == ttb {
        transform: translate(0px, 0px);
      }

      @if $direction == btt {
        transform: translate(0px, 0px);
      }
    }
  }
  // 声明 drawer-out 关键帧
  @keyframes #{$direction}-drawer-out {
    0% {
      @if $direction == ltr {
        transform: translate(0px, 0px);
      }

      @if $direction == rtl {
        transform: translate(0px, 0px);;
      }

      @if $direction == ttb {
        transform: translate(0px, 0px);
      }

      @if $direction == btt {
        transform: translate(0px, 0);
      }
    }

    100% {
      @if $direction == ltr {
        transform: translate(-100%, 0px);
      }

      @if $direction == rtl {
        transform: translate(100%, 0px);
      }

      @if $direction == ttb {
        transform: translate(0px, -100%);
      }

      @if $direction == btt {
        transform: translate(0px, 100%);
      }
    }
  }
}

// 调用处:真正定义关键帧
@include drawer-animation(rtl);
@include drawer-animation(ltr);
@include drawer-animation(ttb);
@include drawer-animation(btt);
// 声明
@mixin animation-in($direction) {
  .el-drawer__open &.#{$direction} {
    animation: #{$direction}-drawer-in .3s 1ms;
  }
}

@mixin animation-out($direction) {
  &.#{$direction} {
    animation: #{$direction}-drawer-out .3s;
  }
}

// 调用
@include b(drawer) {
  @each $direction in $directions {
    @include animation-out($direction);
    @include animation-in($direction);
  }
}

css小技巧

& > :first-child {
  flex: 1;
}
& > * {
  box-sizing: border-box;
}

总结: css样式还是要写全,减少可能产生的问题

.el-drawer__container {
  position: relative;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  height: 100%;
  width: 100%;
}