如何调整函数以使其成为调用它的目标元素?

How to adapt function to make it target element that invoked it?

我在 Bootstrap 4 中编写了以下代码,以便 play/pause 单击视频时,它还会切换视频下方的小扬声器 img。

我不想为我页面上的每个 video/img 对复制这个函数,有没有办法重写这个函数,让它只影响被点击的视频,并以某种方式让它也改变相应的 img?有什么方法可以使用 Class?

<div class="col bg-primary p-0" style="width: 100%; max-width: 787px;">
<div class="bg-danger">
<video id="c20-vid" style="width: 100%; max-width: 787px;" preload="metadata" poster="#.png" playsinline loop>
<source src="#.mp4" type="video/mp4">
</video>
</div>
<div class="text-center captions bg-warning">
<img src="img/muted_icon.png" width="15em" id="c20-mute-icon" />
</div>
</div>

这里是 JavaScript:


function playme() {
    // in this case it's the element that was clicked
    var video = this;
    var muteicon = document.getElementById("c20-mute-icon");
    
    if(video.paused) {
        video.play();
        muteicon.src="img/unmuted_icon.png";
    } 
    else {
        video.pause();
        muteicon.src="img/muted_icon.png";
    }
}

document.getElementById("c20-vid").addEventListener("click", playme);

在HTML中:

<video id=“my-vid" onclick="toggleMute('my-vid', 'my-img');">
    <source src=“my.mp4”>
</video>
<img id="my-img" src="img/muted_icon.png" id=“speaker-icon"  />

在 javascript 中:

function toggleMute(vid, img) { // add parameters
  var video = document.getElementById(vid); // use parameter
  var muteicon = document.getElementById(img); // use parameter
    
  if(video.muted) {
    video.muted = false;
    muteicon.src="img/unmuted_icon.png";
  } 
  else {
    video.muted = true;
    muteicon.src="img/muted_icon.png";
  }
}

我不确定这是您访问视频以静音的方式 - 这取决于您找到 out/be 当然。

听起来您想做两件事:

  1. 编写一个知道其调用上下文的事件处理程序,而不对该上下文进行硬编码。
  2. 查找相对于另一个元素的 HTML 元素。

让我们分别解决这些问题,然后看一个同时执行这两个操作的示例。

编写了解其调用上下文的事件处理程序

这就是 this 的用途:)

来自MDN article on this

When a function is used as an event handler, its this is set to the element on which the listener is placed (some browsers do not follow this convention for listeners added dynamically with methods other than addEventListener()).

简单来说,this是一个特殊的变量,其值会根据调用函数的位置而变化。

.

查找相对于另一个元素的 HTML 元素

Element.querySelector function and DOM Node interface's parent/child/sibling properties 的一些组合通常足以完成这项工作。

综合起来

这是一个将这些想法应用到您的 HTML 结构(包裹在外部 div 中)的片段:

// Define event handler
function toggleMute(e) {
    // "this" comes from the calling context
    // in this case it's the element that was clicked
    var video = this;
    // get the video's parent element and find the first img element inside it
    var muteicon = video.parentElement.querySelector('img');
    
    // do some stuff with these elements
    if(video.muted) {
        video.muted = false;
        video.style.background = "green"
        muteicon.style.background = "yellow";
    } 
    else {
        video.muted = true;
        video.style.background = "orange"
        muteicon.style.background = "teal";
    }
}

// Attach handler to video element, listening for "click" event
document.getElementById('my-vid').addEventListener("click", toggleMute);
video { height: 100px; width: 100px; background: green; }
img { height: 50px; width: 50px; background: yellow; }
<div>
  <video id="my-vid">
      <source src="my.mp4">
  </video>
  <br>
  <img src="img/muted_icon.png" id="speaker-icon" />
</div>

其他可能性

还有其他方法可以让事件处理程序了解其上下文。您还可以使用在调度事件时公开的事件对象,或者在 HTML 中显式传递 this。请参阅下面的示例。我的偏好是避免在 HTML 中内联设置处理程序,因此我会选择第二种或第三种方法。

function ping(target) {
  console.log(target);
  target.classList.toggle('pinged');
  const next = target.nextElementSibling;
  next.classList.toggle('pinged');
  next.nextElementSibling.classList.toggle('pinged');
  
}

function pong() {
  console.log(this);
  this.classList.toggle('ponged');
  this.nextElementSibling.classList.toggle('ponged');
  this.previousElementSibling.classList.toggle('ponged');
}

function pang(e) {
  console.log(e.target);
  e.target.classList.toggle('panged');
  const prev = e.target.previousElementSibling;
  prev.classList.toggle('panged');
  prev.previousElementSibling.classList.toggle('panged');
}

// 'ping' attached to element 'one' inline, in HTML
document.getElementById('two').addEventListener("click", pong);
document.getElementById('three').addEventListener("click", pang);
img {max-height: 200px; max-width: 200px;}
.pinged {filter: sepia(80%)}
.ponged {transform: scale(0.5)}
.panged {opacity: 0.5;}
<img id="one" src="https://www.thewholesomedish.com/wp-content/uploads/2019/06/The-Best-Classic-Tacos-550-500x500.jpg" onclick="ping(this)">

<img id="two" src="https://www.thewholesomedish.com/wp-content/uploads/2019/06/The-Best-Classic-Tacos-550-500x500.jpg">

<img id="three" src="https://www.thewholesomedish.com/wp-content/uploads/2019/06/The-Best-Classic-Tacos-550-500x500.jpg">