怎么穿透上面Dom,触发底层的Dom元素的事件

我的表格中的数据, 是把原数据,
通过 slice()函数 切片,达到分页显示效果

由于表格的行数是固定的,这样就没法, 在table 的样式中, 没法设置 overflow-y:auto 这种滚动条
于是,
另外做了一个滚动条 的子组件 ScrollVue,

问题描述
为了可以在table中任意位置触发滚动事件, 滚动条子组件ScrollVue宽度设置成100% 等同table宽度 :
但是由于, 子组件ScrollVue 在z-index 在最上层 ,
table td中的其它鼠标事件就没法触发了,td 中的 input都没法得到焦点

     求解答

<table>
   
        <ScrollVue  />   // 滚动条 的子组件 是 position定位,width:100%
<thead>
thead>
<tbody>
<tbody>

table>



  // 滚动条 的子组件 ScrollVue  
<template>
    <div ref='scrolldivRef' id='scroll-div' @scroll="scrollMove($event)" :style="{ 'height': rows * 26  + 'px', }"
        v-if="dataLength > rows">
        <div class="scroll-children" :style="{
            'height': dataLength * 26 + 'px',
            // 'top': scrollBlockTop + 'px',
        }" @mousedown="">
        div>
    div>
template>

参考GPT的内容和自己的思路,您可以尝试使用CSS的pointer-events属性来解决此问题。pointer-events属性允许您控制元素是否可以触发鼠标事件。

在您的CSS文件中,为滚动条的子组件添加以下样式:

.scroll-children {
  pointer-events: none;
}


这将使滚动条的子组件不会触发任何鼠标事件,而是将它们传递到下面的元素。然后,您可以为每个需要触发鼠标事件的单元格添加以下样式:

td {
  pointer-events: auto;
}


这将允许每个单元格触发鼠标事件,而不受滚动条子组件的影响。请注意,如果您想在td元素内部的子元素上触发鼠标事件,您也需要为这些子元素添加pointer-events: auto样式。
以下是我修改后的代码:

// 滚动条的子组件 ScrollVue
<template>
  <div
    ref="scrolldivRef"
    id="scroll-div"
    @scroll="scrollMove($event)"
    :style="{ height: rows * 26 + 'px' }"
    v-if="dataLength > rows"
  >
    <div
      class="scroll-children"
      :style="{ height: dataLength * 26 + 'px' }"
      @mousedown=""
    ></div>
  </div>
</template>

<script>
export default {
  name: "ScrollVue",
  props: {
    rows: {
      type: Number,
      default: 10,
    },
    dataLength: {
      type: Number,
      default: 0,
    },
  },
  methods: {
    scrollMove(e) {
      // do something
    },
  },
};
</script>

<style>
.scroll-children {
  pointer-events: none;
}
td {
  pointer-events: auto;
}
</style>

// 在您的模板中,使用 table、thead、tbody 和 tr 元素来创建表格
<table>
  <ScrollVue />
  <thead>
    <tr>
      <th>Header 1</th>
      <th>Header 2</th>
      <th>Header 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><input type="text" placeholder="Input 1" /></td>
      <td><input type="text" placeholder="Input 2" /></td>
      <td><input type="text" placeholder="Input 3" /></td>
    </tr>
    <tr>
      <td><input type="text" placeholder="Input 1" /></td>
      <td><input type="text" placeholder="Input 2" /></td>
      <td><input type="text" placeholder="Input 3" /></td>
    </tr>
    <!-- Add more rows as needed -->
  </tbody>
</table>


请注意,我在样式表中添加了两个规则:.scroll-children 和 td。第一个规则将滚动条子组件的指针事件设置为“none”,因此它不会干扰表格中单元格的事件。第二个规则将所有单元格的指针事件设置为“auto”,这样它们就可以触发鼠标事件了。如果您需要在某些特定的单元格内部禁用鼠标事件,请将它们的pointer-events属性设置为“none”。

回答不易,还请采纳!!!

“Devil组”引证GPT后的撰写:
z-index的值设置为1或者2,这样它就不会覆盖掉位于它下面的table td中的其它鼠标事件。

  • 可能是由于子组件ScrollVue的z-index设置得太高导致的,它会覆盖掉位于它下面的table td中的其它鼠标事件。可以考虑将子组件ScrollVue的z-index设置为一个比较小的值,使得它不会覆盖掉table td中的其它鼠标事件。
  • 另外,如果只是想实现表格的滚动效果,建议直接在table上设置overflow-y:auto,而不是通过切片来实现分页显示。这样可以避免出现子组件覆盖table td的问题,也更符合常规的实现方式。

该回答引用ChatGPT

您可以尝试将滚动条的子组件ScrollVue的z-index设置为比table中的其他元素低,这样就不会遮挡其他元素了。例如,您可以将ScrollVue的z-index设置为1,而将table中其他元素的z-index设置为2或更高。

另外,您可以尝试将滚动条的子组件ScrollVue的pointer-events属性设置为none,这样鼠标事件就可以穿透到下面的元素,从而可以触发table td中的其他鼠标事件。例如,您可以在ScrollVue的样式中添加如下一行代码:

pointer-events: none;

这样,您就可以在table中任意位置触发滚动事件,同时也能触发其他鼠标事件了。

解决方案:

  • 不将滚动条的子组件放在table中,而是将其放在table外部,通过绝对定位或者fixed定位来控制其位置,这样就不会遮盖住表格中的其它元素。

  • 通过JavaScript代码,设置表格的宽度为父容器的宽度减去滚动条的宽度,从而避免滚动条子组件的宽度与表格相同导致的问题。

  • 将滚动条的子组件的z-index设置为与表格相同或者更低,这样就不会遮盖住表格中的其它元素

参考gpt和自己的思路,要想在表格中任意位置触发滚动事件,可以尝试使用 CSS 属性 position: fixed 来让滚动条覆盖在表格之上,这样表格中的元素仍然可以接收鼠标事件。

另外,你也可以尝试在滚动条上使用 CSS 属性 pointer-events: none 来禁用滚动条接收鼠标事件,让底层的元素能够接收到鼠标事件。

修改代码如下:


<style>
    .scroll-vue {
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        width: 16px;
        pointer-events: none;
        /* 其他样式 */
    }
</style>

<table>
    <tbody>
        <!-- 表格内容 -->
    </tbody>
</table>

<template>
    <div class="scroll-vue">
        <!-- 滚动条内容 -->
    </div>
</template>


这样,滚动条就会覆盖在表格上方,但是不会接收鼠标事件,而表格的元素仍然可以接收到鼠标事件。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
问题的根源是子组件的z-index最上层导致遮盖了table中的td元素,而子组件又需要滚动才能展示所有内容。因此,可以考虑使用覆盖整个table的遮罩层来解决覆盖问题,并且在遮罩层中实现滚动条。

具体实现思路如下:

  1. 在table外层包裹一个div,该div作为遮罩层。
  2. 在该div中添加一个子div,作为滚动条,并设置其高度和位置。
  3. 当遮罩层滚动时,同步滚动条的位置。
  4. 当滚动条滚动时,同步遮罩层的位置。
  5. 在遮罩层中设置一个z-index较低的div,用于展示table中的内容。

具体代码示例如下:

<template>
  <div class="table-container">
    <div class="overlay" ref="overlayRef" @scroll="onOverlayScroll">
      <div class="scrollbar" :style="{height: scrollbarHeight + 'px', top: scrollbarTop + 'px'}"
           @scroll.stop.prevent="onScrollbarScroll">
      </div>
      <div class="content">
        <table>
          <thead>
          </thead>
          <tbody>
            <tr v-for="item in displayedData" :key="item.id">
              <td>{{ item.column1 }}</td>
              <td>{{ item.column2 }}</td>
              <td>{{ item.column3 }}</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      data: [], // 原始数据
      currentPage: 1, // 当前页码
      pageSize: 10, // 每页数据条数
      scrollbarHeight: 0, // 滚动条高度
      scrollbarTop: 0, // 滚动条顶部位置
    }
  },
  computed: {
    dataLength() {
      return this.data.length
    },
    totalPages() {
      return Math.ceil(this.dataLength / this.pageSize)
    },
    displayedData() {
      const start = (this.currentPage - 1) * this.pageSize
      const end = this.currentPage * this.pageSize
      return this.data.slice(start, end)
    },
  },
  mounted() {
    this.calculateScrollbarHeight()
  },
  methods: {
    calculateScrollbarHeight() {
      const overlay = this.$refs.overlayRef
      const scrollbar = overlay.querySelector('.scrollbar')
      const content = overlay.querySelector('.content')
      const heightRatio = overlay.clientHeight / content.scrollHeight
      this.scrollbarHeight = overlay.clientHeight * heightRatio
    },
    onOverlayScroll(e) {
      const overlay = e.target
      const scrollbar = overlay.querySelector('.scrollbar')
      const content = overlay.querySelector('.content')
      const heightRatio = overlay.clientHeight / content.scrollHeight
      this.scrollbarHeight = overlay.clientHeight * heightRatio
      this.scrollbarTop = overlay.scrollTop / content.scrollHeight * overlay.clientHeight
    },
    onScrollbarScroll(e) {
      const overlay = this.$refs.overlayRef
      const scrollbar = overlay.querySelector('.scrollbar')
      const content = overlay.querySelector('.content')
      overlay.scrollTop = e.target.scrollTop / scrollbar.clientHeight * content.scrollHeight
    },
  }
}
</script>

<style scoped>
.table-container {
  position: relative;
}

.overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow-y: auto;
  z-index: 0;
}

.scrollbar {
  position: absolute;
  right: 0;
  top: 0;
  width: 10px;
  background-color: #eee;
  z-index: 1;
  overflow-y: scroll;
}

.content {
  position: relative;
  z-index: -1;
}
</style>

在上述代码中,通过overlay容器包含表格和滚动条,以进行滚动。使用计算属性displayedData来计算当前页展示的数据,使用slice函数从data中切分出需要展示的数据。计算属性totalPages用于计算数据的总页数。滚动条的高度通过计算可视区域与内容总高度的比例关系得出,通过scrollbarTop属性记录滚动条顶部的位置,通过监听遮罩层的滚动事件,实时更新滚动条的高度和位置。同时,也在滚动条上添加了@scroll.stop.prevent修饰符,防止默认事件的发生。

最后,在滚动条上添加了@scroll.stop.prevent修饰符,防止默认事件的发生;同时,在遮罩层中,通过设置一个z-index较低的<div>元素,使得表格内容能够展示出来。

通过上述方案,可以解决遮罩层覆盖表格中td元素,以及实现分页展示数据的需求。
如果我的回答解决了您的问题,请采纳!

你可以通过设置ScrollVue的z-index属性来解决这个问题。z-index属性控制元素的堆叠顺序,拥有更高的z-index的元素会覆盖拥有更低的z-index的元素。你可以将ScrollVue的z-index设置的低一些,就可以让table td中的其它鼠标事件可以触发,也可以让td 中的input得到焦点。 你可以在ScrollVue中添加一行:


<div ref='scrolldivRef' id='scroll-div' style="z-index: -1;" @scroll="scrollMove($event)" :style="{ 'height': rows * 26  + 'px', }"
        v-if="dataLength > rows">

这样就可以解决你的问题了。