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

Why class selector is not created on click action?

本文关键字:创建 选择器 单击 操作 为什么      更新时间:2023-09-26

下面是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"点击动作。

由于代码包含在<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元素都会被加载。

注意:你也可以使用load事件在DOM完全加载后执行脚本代码,但这会等待页面上的所有资源(图像,帧等)加载,这对于将事件绑定到元素上是不必要的。参考阅读DOMContentLoaded和Load事件的区别


为什么相同的代码在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>元素的末尾。

现在我们知道了脚本对每个选项的行为,在这里,脚本位置的选项被设置为onLoad,因此代码可以工作。该代码将适用于除No wrap - in Head以外的所有选项。

在jsfiddle docs http://doc.jsfiddle.net/basic/introduction.html#fiddle-settings-sidebar上阅读更多信息

尝试移动script标签并将其放在正文的最末尾。现在的情况是,脚本试图在加载页面上的元素之前运行。将script标签移动到body的底部将确保其上面的所有html元素都已正确加载。