为什么只有其他HTML元素对"点击"?做出反应?

时间:2018-05-26 13:24:27

标签: javascript html event-handling

非常基本 - 作为对"点击"的反应在元素上它的类应该切换。只要只注册一个事件处理程序就可以工作。如果为其他元素注册多个元素,那么只有每个其他元素都会更改它的类。我觉得这与事件冒泡有关,但感觉还不够。我很想知道为什么会这样,以及我如何控制它。所以这就是我到目前为止所得到的:

HTML

<body>
<main>
    <div>
        <p>
        <a>I'm an a-element.</a>
        </p>
    </div>    
</main>     
</body>

CSS

main {
    height: 500px;
    width: 900px;
    background-color: black;}

div {
    height: 400px;
    width: 700px;
    background-color: dimgray;}

p {
    height: 300px;
    width: 500px;
    background-color: darkgray;}

a {
    height: 200px;
    width: 300px;
    background-color: lightgray;}

.gold {
    background-color: gold;}

JS

function setGold(event) {
    event.target.classList.toggle("gold");
}

function setup() {
    document.getElementsByTagName("a")[0].addEventListener("click", setGold);
    document.getElementsByTagName("p")[0].addEventListener("click", setGold);
    document.getElementsByTagName("div")[0].addEventListener("click", setGold);
    document.getElementsByTagName("main")[0].addEventListener("click", setGold);
}

window.addEventListener("load", setup);

2 个答案:

答案 0 :(得分:1)

这是因为click事件起泡e.target是事件所针对的元素(这是同一个元素,实际点击的元素,在每个级别)。因此,当您单击a元素时,会发生以下情况:

  • a上的处理程序切换e.target上的类(a元素)
  • 点击气球至pp上的处理程序切换e.target上的课程(a元素)
  • 点击气球至divdiv上的处理程序切换e.target上的课程(a元素)
  • 点击气球至mainmain上的处理程序切换e.target上的课程(a元素)

偶尔切换一些东西会让你回到起步的地方。 : - )

如果您想在每个级别引用您将处理程序附加到的元素,而不是引用该事件所针对的元素,那么您将使用thise.currentTarget

这可能有助于使其更清晰:

function setGold(event) {
    event.target.classList.toggle("gold");

    console.log("event.target.tagName = " + event.target.tagName);
    console.log("event.currentTarget.tagName = " + event.currentTarget.tagName);
    console.log("this.tagName = " + this.tagName);
}

function setup() {
    document.getElementsByTagName("a")[0].addEventListener("click", setGold);
    document.getElementsByTagName("p")[0].addEventListener("click", setGold);
    document.getElementsByTagName("div")[0].addEventListener("click", setGold);
    document.getElementsByTagName("main")[0].addEventListener("click", setGold);
}

window.addEventListener("load", setup);
main {
    height: 500px;
    width: 900px;
    background-color: black;}

div.x (.as-console) {
    height: 400px;
    width: 700px;
    background-color: dimgray;}

p.x {
    height: 300px;
    width: 500px;
    background-color: darkgray;}

a.x {
    height: 200px;
    width: 300px;
    background-color: lightgray;}

.gold {
    background-color: gold;}
<main>
    <div class="x">
        <p class="x">
        <a class="x">I'm an a-element.</a>
        </p>
    </div>    
</main>

(我在你的元素和CSS中添加了类的原因是,你的CSS影响了in-snippet控制台。)

如果你的目标是切换只是所点击的元素,我会利用click气泡并在main只使用一个处理程序的事实,让它切换e.target的课程:

function setGold(event) {
    event.target.classList.toggle("gold");
}

function setup() {
    document.getElementsByTagName("main")[0].addEventListener("click", setGold);
}

function setGold(event) {
    event.target.classList.toggle("gold");
}

function setup() {
    document.getElementsByTagName("main")[0].addEventListener("click", setGold);
}

window.addEventListener("load", setup);
main {
    height: 500px;
    width: 900px;
    background-color: black;}

div (.as-console) {
    height: 400px;
    width: 700px;
    background-color: dimgray;}

p {
    height: 300px;
    width: 500px;
    background-color: darkgray;}

a {
    height: 200px;
    width: 300px;
    background-color: lightgray;}

.gold {
    background-color: gold;}
<main>
    <div>
        <p>
        <a>I'm an a-element.</a>
        </p>
    </div>    
</main>

如果您要将其过滤为仅切换maindivpa,而不是(例如)span,您可以使用Element#matches查看元素是否与CSS选择器匹配:

function setGold(event) {
    if (event.target.matches("a, p, div, main")) {
        event.target.classList.toggle("gold");
    }
}

function setGold(event) {
    if (event.target.matches("a, p, div, main")) {
        event.target.classList.toggle("gold");
    }
}

function setup() {
    document.getElementsByTagName("main")[0].addEventListener("click", setGold);
}

window.addEventListener("load", setup);
main {
    height: 500px;
    width: 900px;
    background-color: black;}

div (.as-console) {
    height: 400px;
    width: 700px;
    background-color: dimgray;}

p {
    height: 300px;
    width: 500px;
    background-color: darkgray;}

a {
    height: 200px;
    width: 300px;
    background-color: lightgray;}

.gold {
    background-color: gold;}
<main>
    <div>
        <p>
        <a>I'm an a-element.</a>
        <span>I'm a span, I don't toggle</span>
        </p>
    </div>    
</main>

附注:load事件在页面加载周期的后期发生非常,几乎不是在页面上设置点击处理程序的正确位置。而是将script标记放在body的末尾,就在结束</body>标记之前,并立即进行设置。标记上方的HTML定义的所有元素都将存在于该点。更多信息the YUI Guidelines

答案 1 :(得分:1)

使用event.stopPropagation();

function setGold(event) {
    event.stopPropagation();
    event.target.classList.toggle("gold");
}

请查看此内容以获取更多参考 https://www.w3schools.com/jsref/event_stoppropagation.asp