为什么不在单击操作上创建类选择器?

时间:2015-10-03 18:20:01

标签: javascript html css jsfiddle

以下是HTML代码:

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" type="text/css" href="style.css">
    <script type="text/javascript">
    var list = document.querySelector('ul');
    list.addEventListener('click', function(ev) {
        if (ev.target.tagName === 'LI') {
            ev.target.classList.toggle('done');
        }
    }, false);
    </script>
</head>

<body>
    <ul>
        <li>Buy milk</li>
        <li>Take the dog for a walk</li>
        <li>Exercise</li>
        <li>Write code</li>
        <li>Play music</li>
        <li>Relax</li>
    </ul>
</body>

</html>

下面是CSS代码:

li {
  list-style-type: none;
  position: relative;
  margin: 2px;
  padding: 0.5em 0.5em 0.5em 2em;
  background: lightgrey;
  font-family: sans-serif;
}

li.done {
  background: #CCFF99;
}

li.done::before {
  content: '';
  position: absolute;
  border-color: #009933;
  border-style: solid;
  border-width: 0 0.3em 0.25em 0;
  height: 1em;
  top: 1.3em;
  left: 0.6em;
  margin-top: -1em;
  transform: rotate(45deg);
  width: 0.5em;
}

在浏览器上启动时,HTML代码上方的点击操作不会创建class="done"

fiddle上,相同的代码工作正常。

2 个答案:

答案 0 :(得分:7)

由于代码包含在<head>中,因此会在加载<body>的内容之前执行。因此,当绑定事件和事件未绑定时, DOM 中找不到元素。

两种方式来解决此问题。

  1. DOMContentLoaded 事件回调中包含代码。

    document.addEventListener('DOMContentLoaded', function () {
        var list = document.querySelector('ul');
        list.addEventListener('click', function (ev) {
            if (ev.target.tagName === 'LI') {
                ev.target.classList.toggle('done');
            }
        }, false);
    });
    

    更新了小提琴:https://jsfiddle.net/tusharj/pr2hw6c1/

    阅读有关DOMContentLoaded的更多信息:https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

  2. 将代码移至<body> 的末尾,以便在执行脚本时,加载所有 DOM 元素。

  3. 注意: DOM 完全加载后,您还可以使用load事件执行脚本代码,但这样做等待页面上的所有资源(图像,框架等)加载,这对于绑定元素上的事件是不必要的。参考阅读Difference between DOMContentLoaded and Load events

      

    为什么jsfiddle中的相同代码有效?

    jsfiddle为应包含脚本的位置提供了四个选项。您可以从库列表下方的左侧面板中设置此选项。

    1. onLoad:这与窗口的load事件相同。代码包含在load事件的回调中,因此,无法从外部访问函数/变量。防爆。来自HTML内联处理程序。
    2. onDomReady:这与jquery的DOMContentLoadedready相同,此处代码也已包装
    3. No wrap - in Head:这意味着JS代码将添加到head中。 No wrap表示代码未包含在loadDOMContentLoaded中的任何函数中。所以定义的函数/变量是全局的。
    4. No wrap - in Body:脚本在<body>元素的末尾加载。
    5. 现在我们知道脚本对每个选项的行为,在fiddle中,脚本位置选项设置为onLoad,因此代码可以正常工作。该代码适用于除No wrap - in Head之外的所有选项。

      在jsfiddle docs http://doc.jsfiddle.net/basic/introduction.html#fiddle-settings-sidebar

      上阅读更多相关信息

答案 1 :(得分:1)

尝试移动脚本标记并将其放在正文的最末端。它们现在是这样的,脚本试图在页面上的元素加载之前运行。将脚本标记移动到正文的底部将确保其上方的所有html元素都已正确加载。