除了所选元素(this)之外,如何将属性设置为数组中的其他项目?

How to set attributes to the other items in array besides the selected element (this)?

我想在我的 HTML 中制作按钮,而我的一个 JS 类 是 运行 并从后端接收响应。我正在使用 jQuery 和 vanilla JS,并在下面创建了一个示例。在此示例中,我想动态禁用未单击的按钮,以向用户显示正在发生的事情,并且在返回响应之前他们不应单击其他地方。

Array.from(document.getElementsByClassName("upload-button")).forEach(button => {
    button.addEventListener("click",
        function(){
            let buttonSpinner = this.getElementsByTagName("span")[0];
            buttonSpinner.classList.remove("d-none");
            // here I would like to disable the button that wasn't selected
            let destination = this.value;
            uploadData(destination, buttonSpinner);
        }
    )
})

function uploadData(destination, buttonSpinner){
    let link = "https://www.google.com/";
    let description = "Stack Overflow";
    new Upload(link, description, destination, buttonSpinner)
}

class Upload {
  constructor(link=null, description=null, destination="submit", buttonSpinner=null){
    this.link = link;
    this.description = description;
    this.destination = destination;
    this.buttonSpinner = buttonSpinner;
    this.log();
    this.disableButtonSpinner();
  }

  log(){
    console.log(this.link)
   }
  
  wait(){
    return new Promise(resolve => setTimeout(resolve, 3000)); // wait for data to return from backend
  }
  
   async disableButtonSpinner(){
    await this.wait() // simulate backend returning data
    this.buttonSpinner.classList.add("d-none");
   }
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

<div>
    <button class="btn btn-primary upload-button" id="upload-user-data-button" value="data">
        Upload & View My Data
        <span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
        <span class="visually-hidden">Loading...</span>
    </button>
    <button class="btn btn-primary upload-button" id="upload-submit-button" value="submit">
        Upload & Submit
        <span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
        <span class="visually-hidden">Loading...</span>
    </button>
</div>

你可以做类似的事情,循环遍历所有按钮以 disable/re-enable 单击它们。

Array.from(document.getElementsByClassName("upload-button")).forEach((button, index) => {
    button.addEventListener("click",
        function(){
            let buttonSpinner = this.getElementsByTagName("span")[0];
            buttonSpinner.classList.remove("d-none");
            // here I would like to disable the button that wasn't selected
            let buttons = Array.from(document.getElementsByClassName("upload-button"));
            buttons.forEach((button, i)=>{
              i!==index?button.disabled=true:null;
            })
            let destination = this.value;
            uploadData(destination, buttonSpinner);
        }
    )
})

function uploadData(destination, buttonSpinner){
    let link = "https://www.google.com/";
    let description = "Stack Overflow";
    new Upload(link, description, destination, buttonSpinner)
}

class Upload {
  constructor(link=null, description=null, destination="submit", buttonSpinner=null){
    this.link = link;
    this.description = description;
    this.destination = destination;
    this.buttonSpinner = buttonSpinner;
    this.log();
    this.disableButtonSpinner();
  }

  log(){
    console.log(this.link)
   }
  
  wait(){
    return new Promise(resolve => setTimeout(resolve, 3000)); // wait for data to return from backend
  }
  
   async disableButtonSpinner(){
    await this.wait() // simulate backend returning data
    this.buttonSpinner.classList.add("d-none");
    let buttons = Array.from(document.getElementsByClassName("upload-button"))
    buttons.forEach(button=>button.disabled=false)
   }
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

<div>
    <button class="btn btn-primary upload-button" id="upload-user-data-button" value="data">
        Upload & View My Data
        <span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
        <span class="visually-hidden">Loading...</span>
    </button>
    <button class="btn btn-primary upload-button" id="upload-submit-button" value="submit">
        Upload & Submit
        <span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
        <span class="visually-hidden">Loading...</span>
    </button>
</div>

你可以在函数中加一个参数来访问我用e的点击事件。然后您可以遍历按钮并禁用除事件目标以外的其他功能。这是通过 Array.from(document.getElementsByClassName("upload-button")).forEach(insideButton => { if(e.target !== insideButton) insideButton.disabled = true});

实现的

  Array.from(document.getElementsByClassName("upload-button")).forEach(button => {
        button.addEventListener("click",
            function(e){
                let buttonSpinner = this.getElementsByTagName("span")[0];
                buttonSpinner.classList.remove("d-none");
                // here I would like to disable the button that wasn't selected        
                 Array.from(document.getElementsByClassName("upload-button")).forEach(insideButton => {
                 if(e.target !== insideButton) 
                 insideButton.disabled = true});
                let destination = this.value;
                uploadData(destination, buttonSpinner);
            }
        )
    })

    function uploadData(destination, buttonSpinner){
        let link = "https://www.google.com/";
        let description = "Stack Overflow";
        new Upload(link, description, destination, buttonSpinner)
    }

    class Upload {
      constructor(link=null, description=null, destination="submit", buttonSpinner=null){
        this.link = link;
        this.description = description;
        this.destination = destination;
        this.buttonSpinner = buttonSpinner;
        this.log();
        this.disableButtonSpinner();
      }

      log(){
        console.log(this.link)
       }
      
      wait(){
        return new Promise(resolve => setTimeout(resolve, 3000)); // wait for data to return from backend
      }
      
       async disableButtonSpinner(){
        await this.wait() // simulate backend returning data
        this.buttonSpinner.classList.add("d-none");
       }
    }
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    <div>
        <button class="btn btn-primary upload-button" id="upload-user-data-button" value="data">
            Upload & View My Data
            <span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
            <span class="visually-hidden">Loading...</span>
        </button>
        <button class="btn btn-primary upload-button" id="upload-submit-button" value="submit">
            Upload & Submit
            <span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
            <span class="visually-hidden">Loading...</span>
        </button>
    </div>

添加此解决方案以解决 @Raven 解决方案的问题,即即使在操作完成后按钮仍处于禁用状态。

Array.from(document.getElementsByClassName("upload-button")).forEach(button => {
        button.addEventListener("click",
            async function(e){
                let buttonSpinner = this.getElementsByTagName("span")[0];
                buttonSpinner.classList.remove("d-none");
                // here I would like to disable the button that wasn't selected        
                 Array.from(document.getElementsByClassName("upload-button")).forEach(insideButton => {
                    if(e.target !== insideButton) 
                    insideButton.disabled = true}
                 );
                let destination = this.value;
                await uploadData(destination, buttonSpinner);
            }
        )
    })

    async function uploadData(destination, buttonSpinner){
        let link = "https://www.google.com/";
        let description = "Stack Overflow";
        await new Upload(link, description, destination, buttonSpinner)
    }

    class Upload {
      constructor(link=null, description=null, destination="submit", buttonSpinner=null){
        this.link = link;
        this.description = description;
        this.destination = destination;
        this.buttonSpinner = buttonSpinner;
        this.log();
        this.disableButtonSpinner();
      }

      log(){
        console.log(this.link)
       }
      
      wait(){
        return new Promise(resolve => setTimeout(resolve, 3000)); // wait for data to return from backend
      }
      
       async disableButtonSpinner(){
        await this.wait().then(()=>{
            Array.from(document.getElementsByClassName("upload-button")).forEach(insideButton => {    
                insideButton.disabled = false;
            }
             );
        }) // simulate backend returning data
        this.buttonSpinner.classList.add("d-none");
       }
    }
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    <div>
        <button class="btn btn-primary upload-button" id="upload-user-data-button" value="data">
            Upload & View My Data
            <span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
            <span class="visually-hidden">Loading...</span>
        </button>
        <button class="btn btn-primary upload-button" id="upload-submit-button" value="submit">
            Upload & Submit
            <span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
            <span class="visually-hidden">Loading...</span>
        </button>
    </div>