为什么我的 jQuery 单击处理程序就像我单击 parent 元素一样?

Why is my jQuery click handler acting as though I clicked on the parent element?

我在 parent div 中创建了很多 child div。所有div定位,parentdiv是绝对的,childdiv是相对的。 Parentdivz-index是400,childdiv是500。

当我点击任何 child div 然后 jQuery 检测 parent div 与点击功能。我不明白为什么这些代码不起作用。

所以我希望任何人都可以帮助我这种情况。

Parent div ID: "#cardslayer"

Child divs class: ".cardinlayer"

-HTML:

<body>
<div id="cardslayer"></div>
</body>

-CSS:

#cardslayer {
    position: absolute;
    width: 960px;
    height: auto;
    top: 0;
    left: 0;
    z-index: 400;
    display: none;
}

.cardinlayer {
    width: 100px;
    height: 125px;
    margin: 10px;
    position: relative;
    z-index: 500;
    display: none;
}

-JQUERY:(css 中的某些样式具有 jquery 功能。)

  var hazakstr = "";
  var i = 0;
  

  $("#button").click(function(){
      hazakstr = "<center>";
      for(i=0; i<22; i++) {
        if(level_owner[i] == -1) {
            hazakstr = hazakstr + "<div class='cardinlayer' id='house" + i + "' style='background: url(../houses/" + i + ".png); background-size: 100px 125px; background-repeat: no-repeat;'></div>";
        }
      }
      hazakstr = hazakstr + "</center>";
      $("#cardslayer").css("display", "block");
      $("#cardslayer").html(hazakstr);
      $(".cardinlayer").css("display", "inline-block");
      i=((567 - $("#cardslayer").height()) / 2);
      $("#cardslayer").css("height", 567 - i + "px");
      $("#cardslayer").css("padding-top", i + "px");
  });

在循环结束时将 html 添加到 #cardslayer。代码如下:

HTML:

<div id="cardslayer" style="display: block; height: 507px; padding-top: 60px;">
    <center>
        <div class="cardinlayer" id="house0" style="background: url(&quot;../houses/0.png&quot;) 0% 0% / 100px 125px no-repeat; display: inline-block;"></div>
        <div class="cardinlayer" id="house1" style="background: url(&quot;../houses/1.png&quot;) 0% 0% / 100px 125px no-repeat; display: inline-block;"></div>
        .
        .
        .
        .
        <div class="cardinlayer" id="house21" style="background: url(&quot;../houses/21.png&quot;) 0% 0% / 100px 125px no-repeat; display: inline-block;"></div>
    </center>
</div>  

所以毕竟我为.cardinlayer创建了点击功能。而且它不起作用。

$(".cardinlayer").click(function(){
      alert("Cardinlayer");
  });

我为 .cardinlayer 尝试了这个点击功能

$("div").click(function(){
    alert($(this).attr("id"));
});

当我点击一个 .cardinlayer return 值是#cardslayer,而不是#house1 或任何#house。

#cardslayer 是 parent 和 .cardinlayer(s) 是 childs.

问题图片: https://i.imgur.com/DjWcIKK.jpg

红色是 parent,蓝色是 child。 所以当我点击任何卡片时 jquery 都没有被检测到。 Jquery 想我点击了褪色的黑色背景。 (parent).

我希望有人能帮助我。 祝你有愉快的一天,谢谢。

click 事件有修饰符,例如 stopPropagationpreventDefault。 (更多信息:Event on MDN

查看实际效果:

let hazakstr = "";

const cardHtml = ({ i }) => {
  return `
    <div
      id="house${i}"
      class="cardinlayer"
      data-idx="${i}"
    >
      HOUSE ${i}
    </div>
  `
}


jQuery("#button").on('click', function() {
  for (let i = 0; i < 22; i++) {
    hazakstr += cardHtml({ i })
  }
  $("#cardslayer").html(hazakstr);
});

jQuery("#cardslayer").on('click', '.cardinlayer', function(e) {
  e.stopPropagation() // this stops the event from propagation
  const { idx } = $(this).data()
  alert(`Clicked house card: ${idx}`)
})
.container {
  position: relative;
}

#cardslayer {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}

.cardinlayer {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 125px;
  padding: 8px 16px;
  background-color: rgba(255, 0, 0, 0.3);
  -webkit-transition: background-color 0.25s ease-out;
  -moz-transition: background-color 0.25s ease-out;
  -o-transition: background-color 0.25s ease-out;
  transition: background-color 0.25s ease-out;
  cursor: pointer;
}

.cardinlayer:hover {
  background-color: rgba(255, 0, 0, 0.9)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="button">CLICK</button>
<div class="container">
  <div id="cardslayer"></div>
</div>


编辑/建议:

我建议您尽可能不要乱用 jQueryVue:

中有一些更新

Vue.component('HouseCard', {
  props: ['idx'],
  methods: {
    onClick({ idx }) {
      alert(`Clicked house: ${ idx }`)
    },
  },
  template: `
    <div
      class="cardinlayer"
      @click.stop="() => onClick({ idx })"
    >
      HOUSE {{ idx }}
    </div>
  `
})

new Vue({
  el: "#app",
  data() {
    return {
      houses: [],
    }
  },
  methods: {
    addHouse(houses) {
      return [...houses, houses.length]
    },
    add1House() {
      this.houses = this.addHouse(this.houses)
    },
    add22Houses() {
      let ret = this.houses
      for (let i = 0; i < 22; i++) {
        ret = this.addHouse(ret)
      }
      this.houses = ret
    }
  },
  template: `
    <div>
      <button @click="add1House">ADD 1 HOUSE</button>
      <button @click="add22Houses">ADD 22 HOUSES</button>
      <br />
      <div
        class="container"
      >
        <div
          id="cardslayer"
        >
          <house-card
            v-for="(house, idx) in houses"
            :key="idx"
            :idx="idx"
          ></house-card>
        </div>
      </div>
    </div>
  `
})
.container {
  position: relative;
}

#cardslayer {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}

.cardinlayer {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 125px;
  padding: 8px 16px;
  background-color: rgba(255, 0, 0, 0.3);
  -webkit-transition: background-color 0.25s ease-out;
  -moz-transition: background-color 0.25s ease-out;
  -o-transition: background-color 0.25s ease-out;
  transition: background-color 0.25s ease-out;
  cursor: pointer;
}

.cardinlayer:hover {
  background-color: rgba(255, 0, 0, 0.9)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

React解决方案:

const { useState } = React

const HouseCard = ({ idx }) => {
  const handleClick = () => {
    alert(`House clicked: ${idx}`)
  }
  return (
    <div class="cardinlayer" onClick={handleClick}>
      HOUSE { idx }
    </div>
  )
}

const App = () => {
  const [houses, setHouses] = useState([])
  
  const addHouse = (houses) => [...houses, houses.length]
  const add1House = () => setHouses((prev) => addHouse(prev))
  const add22Houses = () => {
    for(let i = 0; i < 22; i++) {
      setHouses((prev) => addHouse(prev))
    }
  }
  
  return (
    <div>
      <button onClick={add1House}>ADD 1 HOUSE</button>
      <button onClick={add22Houses}>ADD 22 HOUSES</button>
      <div class="container">
        <div id="cardslayer">
          {
            houses.map((_, idx) => <HouseCard idx={idx} />)
          }
        </div>
      </div>
    </div>
  )
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
.container {
  position: relative;
}

#cardslayer {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}

.cardinlayer {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 125px;
  padding: 8px 16px;
  background-color: rgba(255, 0, 0, 0.3);
  -webkit-transition: background-color 0.25s ease-out;
  -moz-transition: background-color 0.25s ease-out;
  -o-transition: background-color 0.25s ease-out;
  transition: background-color 0.25s ease-out;
  cursor: pointer;
}

.cardinlayer:hover {
  background-color: rgba(255, 0, 0, 0.9)
}
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>

<div id="root"></div>