在 JavaScript / jQuery 回调中使用 'this' 更改点击元素的文本

Change the text of clicked element with 'this' in JavaScript / jQuery callback

谁能解释一下回调中的 this

例子。 网页。

<html>
<head>
  <script src="https://code.jquery.com/jquery-1.11.2.js"></script>
  <script src="myApp.js"></script>
</head>
<body>
  <button type="button" id="btn001">Show</button><br/>
  <p id="p001" class="article">Some contents...</p>
  <button type="button" id="btn002">Show</button><br/>
  <p id="p002" class="article">Other content...</p>
  <!-- more paragraphs -->
</body>
</html>

首先,我为每个段落编写了一个函数。 myApp.js.

的源代码
$(document).ready(function () {
  // hide all articles at the begining
  $(".article").hide();
  // button 1 hides/shows first paragraph
  $("#btn001").click(function () {
    if ($(this).html() === "Show") {
      $(this).html("Hide");
    } else {
      $(this).html("Show");
    }
    $("#p001").toggle();
  });
  // button 2 hides/shows second paragraph
  $("#btn002").click(function () {
    if ($(this).html() === "Show") {
      $(this).html("Hide");
    } else {
      $(this).html("Show");
    }
    $("#p002").toggle();
  });
  // repeat code for next paragraphs
});

我对代码重复很生气,所以我尝试排除代码来运行。

function handleHideShow(par) {
  if ($(this).html() === "Show") {
    $(this).html("Hide");
  } else {
    $(this).html("Show");
  }
  par.toggle();
}

$(document).ready(function () {
  // hide all articles at the begining
  $(".article").hide();
  // button 1 hides/shows first paragraph
  $("#btn001").click(function () {
    handleHideShow($("#p001"));
  });
  // button 2 hides/shows second paragraph
  $("#btn002").click(function () {
    handleHideShow($("#p002"));
  });
});

切换段落有效,但 button 上的文本没有改变。谁能解释一下 this 发生了什么?

以及如何解决这个问题?

调用函数时没有特殊上下文,this 不是元素。
改为引用函数

$("#btn001").click(handleHideShow);
$("#btn002").click(handleHideShow);

function handleHideShow() {
    $(this).html(function (_, html) {
        return html === "Show" ? "Hide" : "Show";
    });

    $('#' + this.id.replace('btn', 'p')).toggle();
}

FIDDLE

函数中需要传递按钮对象:

试试这个:

function handleHideShow(par,that) {
  if ($(that).html() === "Show") {
    $(that).html("Hide");
  } else {
    $(that).html("Show");
  }
  par.toggle();
}

$(document).ready(function () {
  // hide all articles at the begining
  $(".article").hide();
  // button 1 hides/shows first paragraph
  $("#btn001").click(function () {
    handleHideShow($("#p001"),this);
  });
  // button 2 hides/shows second paragraph
  $("#btn002").click(function () {
    handleHideShow($("#p002"),this);
  });
});

或者你也试试这个:

$(document).ready(function () {
  // hide all articles at the begining
  $(".article").hide();
  // button 1 hides/shows first paragraph
  $("button[id^='btn']").click(function () {
    if ($(this).html() === "Show") {
      $(this).html("Hide");
    } else {
      $(this).html("Show");
    }
    $(this).next().toggle();
  });
});

上面的代码是最优的,你可以添加任意数量的按钮。

您的第一个函数是事件处理程序。使用事件处理程序 $(this) 自动引用被单击、更改、悬停等的元素。jQuery 为您创建 $(this),虽然您无法明确看到它传递到函数它对点击处理程序回调中的所有代码可用。

您的第二个函数是一个简单函数,不是事件处理程序,因此 jQuery 不会为您创建 $(this) 引用

在您的代码中,您可以从您的事件处理程序传递 $(this),如 handleHideShow($(this),$("#p002"));,并在您的函数中引用它,如 function handleHideShow(btn, par)。然后,在 handleHideShow 内,btn 将引用与点击处理程序中引用的 $(this) 相同的元素(请参阅下面的第二个代码段)。

但是,我会通过给按钮和段落 类 而不是 id 来简化代码,然后这样做:

$(document).ready(function () {
  $('.article').hide();
  $('.myBtn').click(function(){
    $(this).html( $(this).html() == 'Show' ? 'Hide' :'Show' );
    $(this).nextAll('.article').first().toggle();
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
    <html>
    <head>
      <script src="https://code.jquery.com/jquery-1.11.2.js"></script>
      <script src="myApp.js"></script>
    </head>
    <body>
      <button type="button" class="myBtn">Show</button><br/>
      <p class="article">Some contents...</p>
      
      <button type="button" class="myBtn">Show</button><br/>
      <p class="article">Other content...</p>
      <!-- more paragraphs -->
    </body>
    </html>

现在,有人可能会争辩说这效率较低,因为 jQuery 必须搜索更多元素才能找到段落,但我相信它会更可靠,因为您可以添加尽可能多的按钮和段落就像不用担心所有顺序的 id 一样。老实说,您必须有一个非常大的网页才能看到任何性能问题。

$(document).ready(function () {
  // hide all articles at the begining
  $(".article").hide();
  // button 1 hides/shows first paragraph
  $("#btn001").click(function () {
    handleHideShow($(this),$("#p001"));
  });
  // button 2 hides/shows second paragraph
  $("#btn002").click(function () {
    handleHideShow($(this),$("#p002"));
  });
});

function handleHideShow(btn, par) {
  if (btn.html() === "Show") {
    btn.html("Hide");
  } else {
    btn.html("Show");
  }
  par.toggle();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<html>
<head>
  <script src="https://code.jquery.com/jquery-1.11.2.js"></script>
  <script src="myApp.js"></script>
</head>
<body>
  <button type="button" id="btn001">Show</button><br/>
  <p id="p001" class="article">Some contents...</p>
  
  <button type="button" id="btn002">Show</button><br/>
  <p id="p002" class="article">Other content...</p>
  <!-- more paragraphs -->
</body>
</html>