JavaScript 如何在 onchange 事件和选择元素中使用“this”

问题描述

我的 html 中有几个选择标签和 div:

<div>
    <select name="one" id="oneId" class="selectOne" onchange="myFunction()">
        <option value="" disabled selected>choose*</option>
        <option value="1">Yes</option>
        <option value="2">No</option>
    </select>
    <div class="show" style="display:none;">
        <input type="number" value="" id="other"></input>
    </div>
</div>

现在我想做这样的事情:

function myFunction() {
    var a = this.value; // to select this "select tag" of this function
    var b = this.closest("show"); // to select closest "show div" to select tag
    var c = b.children; //input // to select input in "show div"

    if (a == 1) {
        b.style.display = "block";
        c.removeAttribute("disabled");
    } else {
        b.style.display = "none";
        c.setAttribute('disabled','disabled');
    }
}

function myFunction() {
  var a = this.value; // to select this "select tag" of this function
  var b = this.closest("show"); // to select closest "show div" to select tag
  var c = b.children; //input // to select input in "show div"

  if (a == 1) {
    b.style.display = "block";
    c.removeAttribute("disabled");
  } else {
    b.style.display = "none";
    c.setAttribute('disabled','disabled');
  }
}
<div>
  <select name="one" id="oneId" class="selectOne" onchange="myFunction()">
    <option value="" disabled selected>choose*</option>
    <option value="1">Yes</option>
    <option value="2">No</option>
  </select>
  <div class="show" style="display:none;">
    <input type="number" value="" id="other"></input>
  </div>
</div>

主要问题是选择合适的元素(阅读评论标签)

解决方法

引用事件目标

this 将根据侦听器功能添加到元素的方式而有所不同。

您可以使用...添加侦听器

  1. ……EventTarget.addEventListener()this 将是它添加到的元素。
  2. HTMLElement.onevent – 其中 event of .onevent 是实际事件名称。 this 将是它添加到的元素。
  3. ... 内联 onevent 侦听器(例如,使用 HTML 属性 onchange="myFunction()")。 this 将是全局对象,请参阅 globalThis

出于多种原因,通常建议使用 EventTarget.addEventListener()。以下是您应该使用它的众多原因中的两个:

  1. 它允许添加多个侦听器,而不仅仅是一个。
  2. 使用它将使您的 HTML 远离 JavaScript,将功能与结构分开。使用 JavaScript 来添加功能,而不是 HTML。

这是一个演示添加侦听器方法的示例:

document.querySelector('button').addEventListener('click',log); // Case 1
document.querySelector('button:nth-child(2)').onclick = log; // Case 2

function log() {
  console.log((this === globalThis ? "'this' is 'globalThis'" : this));
}
<button>Using addEventListener()</button>
<button>Using Element.onclick</button>
<button onclick="log()">Using onevent-listener</button> <!-- Case 3 -->

为了使其更加一致,可以使用 Event.target。事件对象通常作为第一个参数传递。使用内联 onevent 侦听器需要您自己传递事件对象 event

使用 Event.target 将始终返回事件目标,无论您选择以何种方式添加侦听器。

修改后的代码如下:

document.querySelector('button').addEventListener('click',log); // Case 1
document.querySelector('button:nth-child(2)').onclick = log; // Case 2

function log(evt) {
  console.log((evt.target === globalThis ? 'test' : evt.target));
}
<button>Using addEventListener()</button>
<button>Using Element.onclick</button>
<button onclick="log(event)">Using onevent-listener</button> <!-- Case 3 -->

查找与某个元素相关的其他元素

这是通过使用 ElementDocument.querySelector() 函数来查询子代,以及使用 Element.closest() 函数来查询祖先来实现的。这两个函数都需要传递一个包含 CSS selectors 的字符串。

如果您需要查找相邻的兄弟姐妹,您可以使用 Node.nextSiblingNode.previousSibling 查找相邻的 Node 兄弟姐妹。这还包括 TextNode 和类似的非元素节点。
要仅查找相邻元素同级,请使用 Element.nextElementSiblingElement.previousElementSibling

如果您的 <div class="show"> 始终是您的 <select> 之后的以下元素,您可以简单地使用 .nextElementSibling 如下:

document.querySelector('select').addEventListener('change',selectChanged);

function selectChanged(evt) {
  var divShow = evt.target.nextElementSibling;
  
  divShow.style.display = evt.target.value;
}
<select>
  <option disabled selected>Choose</option>
  <option value="block">Show &lt;div&gt;</option>
  <option value="none">Hide &lt;div&gt;</option>
</select>
<div class="show" style="display:none">
  This &lt;div&gt; is shown.
</div>

,

this 指的是 onchange 函数内的 select 元素。

您正在从该函数调用 myFunction(),因此,as per the standard rulesthis 将是 window 内的 myFunction

如果您想传递元素,则需要显式传递(作为参数或使用 applycall)。


更好的是,不要使用内在事件属性(它有各种各样的问题),而是使用 addEventListener


一旦你解决了这个问题,你就会发现你使用的 closest 完全错误。

它搜索祖先而不是兄弟姐妹(所以你可能想要this.parentElement.querySelector),并且像querySelector一样需要一个选择器而不是一个普通的类名。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...