核心是要 给其父元素设置 position: relative;

在这里插入图片描述
2. 然后还要给 el-drawer设置样式 position:absolute; 注意参考官方文档,
需要 append-to-body: false, 因为设置为true会插入body
在这里插入图片描述
3. 之后就是 蒙层 也要插入到指定位置;首先设置两个属性也就是隐藏el-drawer自带的蒙层
:modal-append-to-body=“false” // 遮罩层不能插入至 body
:modal=“false” // 不需要遮罩层
:wrapperClosable= “false”, // 点击遮罩层不可关闭drawer
4. 然后就是写自己的 蒙层:


在el-drawer出现的实现 出现该蒙层
5. 设置样式:

.drawer_mask {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.5);
}

下面进行改进,支持在指定div打开,而且支持嵌套。主要还是利用给父亲dom设置position属性。
主要解决的问题是:
1.1. 嵌套的drawer需要设置position:absolute,如果不是嵌套的drawer,只调用一次的情况,需要手动设置其 父dom为position:relative
解决:

 mounted() {
    // 获取一级父组件和子组件
    // 设置在指定的 包裹该子组件的父dom节点打开 抽屉
    const fatherDom = this.$parent.$el
    const allCss = window.getComputedStyle(fatherDom, null)
    console.log(allCss.position, fatherDom.classList, Array.from(fatherDom.classList).includes('el-drawer__wrapper'), 'allCssallCss')
    if (Array.from(fatherDom.classList).includes('el-drawer__wrapper')) {
      fatherDom.style.position = 'absolute'
    } else {
      if (allCss.position == 'static') {
        // 不是el-drawer
        fatherDom.style.position = 'relative'
      }
    }
  },

1.2 嵌套的drawer 如果在父组件 引用的时候,可能有人会设置positon:absolute,这样会影响子drawer的定位。所以需要加入判断,移除这个属性,设置为position:static。

问题:
在这里插入图片描述
解决:

onOpen() {
      // Drawer 的内容是懒渲染的,即在第一次被打开之前,
      // 传入的默认 slot 不会被渲染到 DOM 上。
      // 因此,如果需要执行 DOM 操作,
      // 或通过 ref 获取相应组件,请在 open 事件回调中进行。
      this.$nextTick(() => {
        // // 只有一个div dom传入,清除在父组件使用slot时候 传入的position属性
        if (this.$slots.default && this.$slots.default.length === 1) {
          console.log(this.$slots.default[0], 'defaultSlots')
          this.$slots.default[0].elm.style = `
          position : static !important
          ` // 默认值,元素的位置有文档流决定,不受top,left等影响
        }
      })
    }

<template>
  <div>
    <div v-show="visible" class="drawer_mask" />
    <el-drawer
      ref="elDrawer"
      :title="title"
      :visible="visible"
      :append-to-body="false"
      :modal-append-to-body="false"
      :modal="false"
      style="position: absolute;"
      :direction="direction"
      :size="size"
      :wrapper-closable="false"
      destroy-on-close
      @close="onClose"
      @open="onOpen"
    >
      <div>
        <slot />
      </div>
    </el-drawer>
  </div>
</template>

<script>
export default {
  name: 'CustElDrawer',
  props: {
    title: {
      type: String,
      default: '测试'
    },
    visible: {
      type: Boolean,
      default: false
    },
    direction: {
      type: String,
      default: 'rtl'
    },
    size: {
      type: [String, Number],
      default: '30%'
    }
  },
  mounted() {
    // 获取一级父组件和子组件
    // 设置在指定的 包裹该子组件的父dom节点打开 抽屉
    const fatherDom = this.$parent.$el
    const allCss = window.getComputedStyle(fatherDom, null)
    console.log(allCss.position, fatherDom.classList, Array.from(fatherDom.classList).includes('el-drawer__wrapper'), 'allCssallCss')
    if (Array.from(fatherDom.classList).includes('el-drawer__wrapper')) {
      fatherDom.style.position = 'absolute'
    } else {
      if (allCss.position == 'static') {
        // 不是el-drawer
        fatherDom.style.position = 'relative'
      }
    }
  },
  methods: {
    onClose() {
      this.$emit('close')
    },
    onOpen() {
      // Drawer 的内容是懒渲染的,即在第一次被打开之前,
      // 传入的默认 slot 不会被渲染到 DOM 上。
      // 因此,如果需要执行 DOM 操作,
      // 或通过 ref 获取相应组件,请在 open 事件回调中进行。
      this.$nextTick(() => {
        // // 只有一个div dom传入,清除在父组件使用slot时候 传入的position属性
        if (this.$slots.default && this.$slots.default.length === 1) {
          console.log(this.$slots.default[0], 'defaultSlots')
          this.$slots.default[0].elm.style = `
          position : static !important
          ` // 默认值,元素的位置有文档流决定,不受top,left等影响
        }
      })
    }
  }
}
</script>

  <style lang="scss" scoped>
      .drawer_mask {
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
        background: rgba(255, 255, 255, 0.5);
      }
  </style>

Logo

前往低代码交流专区

更多推荐