首页 > 解决方案 > 重构:希望单个函数/事件处理程序做同样的事情

问题描述

从我的代码中可以看出,我是编程和 JS 的新手。页面上的背景颜色和文本会根据<li>单击的目标标记而变化,例如函数、对象、数组或使用eventListeners事件处理程序的 if 语句。

我在这里寻找灵感,以便最终了解编程的真正工作原理。

请参阅下面的代码。

let navLink1 = document.querySelector('color1');
let navLink2 = document.querySelector('color2');
let navLink3 = document.querySelector('color3');
let navLink4 = document.querySelector('color4');

let p1 = document.querySelector('para');

navLink1.addEventListener('click', function (e) {
    document.body.style.background = "color1";
    document.innerHTML(p1) = "New text!";  
});

navLink2.addEventListener('click', function (e) {
    document.body.style.background = "color2";
    document.innerHTML(p1) = "New text!";  
});

navLink3.addEventListener('click', function (e) {
    document.body.style.background = "color3";
    document.innerHTML(p1) = "New text!";
});

navLink4.addEventListener('click', function (e) {
    document.body.style.background = "color4";
    document.innerHTML(p1) = "New text!";
});
<ul class ='nav'>
   <li class ='color1'><a href=''>color1</a></li>
   <li class ='color2'><a href=''>color2</a></li>
   <li class ='color3'><a href=''>color3</a></li>
   <li class ='color4'><a href=''>color4</a></li>
</ul>

<h2>The text in the <p> tag below changes according to clicked link in the menu</h2>

<p class ='para'>This is (color)</p>
<!-- if color1 is clicked in the menu then the <body> background will be changed to color1 and the innerHTML will also be changed to color1. The background color and targeted text changes according to the menu item clicked ->

标签: javascriptdom-eventsjavascript-objects

解决方案


该代码存在一些问题,但基本上:是的,您可以使用单个事件处理程序来处理所有四个链接。这个过程称为“事件委托”——将事件的处理委托给某个祖先元素。在这种情况下,这ul是放置click处理程序的好地方。click事件“冒泡”从目标元素 (the li) 到它的父元素,然后是li的父元素等等,所以我们可以ul通过在ul.

看评论:

// Handle click on the `ul.nav`:
document.querySelector(".nav").addEventListener("click", function(event) {
    // `event.target` is the element the event was targeted at (the `li`
    // element). We can use the `closest` method to find the first element
    // starting with that one and then working through its parent, parent's
    // parent, etc., until we find one that matches the selector. The
    // selector looks for an element that has a `data-color` attribute.
    const li = event.target.closest("[data-color]");
    // If we found one and it's within the element we hooked `click` on
    // (the `ul`), we handle the click
    if (li && this.contains(li)) {
        // Get the color from the attribute
        const color = li.getAttribute("data-color");
        // Assign it to the body
        document.body.style.backgroundColor = color;
        // Show the color name in the `span`
        document.querySelector(".color").textContent = color;
    }
});
li[data-color] {
    cursor: pointer;
}
<ul class="nav">
    <!-- I've removed the classes and set a data-* attribute with the color to set -->
    <!-- I've also removed the `a` elements. Because they're links, clicking follows them -->
    <li data-color="#E0E0E0">color1</li>
    <li data-color="#D0D0D0">color2</li>
    <li data-color="#C0C0C0">color3</li>
    <li data-color="#B0B0B0">color4</li>
</ul>

<!-- Note that I've changed the opening angle bracket in the `p` tag below to its
     character reference form (&lt;) so it's not handled as a paragraph -->
<h2>The text in the &lt;p> tag below changes according to clicked link in the menu</h2>

<!-- I've added a span with a class so we can set the color name -->
<p class="para">This is <span class="color">(no color yet)</span></p>

更多的

如果你想用元素来做这件事a(所以我们在各种用户手势上获得默认的选项卡和“激活”,比如按下Enter),我们可以做同样的事情,只需调用告诉浏览器event.preventDefault()不要跟随href. a这样做时,通常最好让href用户知道它要做什么,所以我们可以使用它而不是data-*属性:

// The prefix used on `a` element `href`s:
const prefix = "#set-color-";

// Handle click on the `ul.nav`:
document.querySelector(".nav").addEventListener("click", function(event) {
    // `event.target` is the element the event was targeted at (the `li`
    // element). We can use the `closest` method to find the first element
    // starting with that one and then working through its parent, parent's
    // parent, etc., until we find one that matches the selector. The
    // selector looks for an `a` element whose `href` *starts with* the
    // text `set-color-`
    const anchor = event.target.closest(`a[href^="${prefix}"]`);
    // If we found one and it's within the element we hooked `click` on
    // (the `ul`), we handle the click
    if (anchor && this.contains(anchor)) {
        // Get the color from the `href` by grabbing the part after the
        // prefix
        const color = anchor.getAttribute("href").substring(prefix.length);
        // Assign it to the body
        document.body.style.backgroundColor = color;
        // Show the color name in the `span`
        document.querySelector(".color").textContent = color;
        // Prevent the default of following the anchor
        event.preventDefault();
    }
});
li[data-color] {
    cursor: pointer;
}
<ul class="nav">
    <!-- I've removed the classes and set a data-* attribute with the color to set -->
    <!-- I've also removed the `a` elements. Because they're links, clicking follows them -->
    <li><a href="#set-color-#E0E0E0">color1</a></li>
    <li><a href="#set-color-#D0D0D0">color2</a></li>
    <li><a href="#set-color-#C0C0C0">color3</a></li>
    <li><a href="#set-color-#B0B0B0">color4</a></li>
</ul>

<!-- Note that I've changed the opening angle bracket in the `p` tag below to its
     character reference form (&lt;) so it's not handled as a paragraph -->
<h2>The text in the &lt;p> tag below changes according to clicked link in the menu</h2>

<!-- I've added a span with a class so we can set the color name -->
<p class="para">This is <span class="color">(no color yet)</span></p>


推荐阅读