【问题标题】:forEach loop skips modal openingforEach 循环跳过模态打开
【发布时间】:2021-01-08 13:45:06
【问题描述】:

我有一个包含 n 个单词的数组。我正在运行一个 forEach 循环来遍历每个元素,对于每个元素,它都应该打开一个带有文本输入的模态,单击按钮后,该值将存储在一个新数组中,并且模态消失。那么同样的事情应该发生 n 次。

我已经在提示下对其进行了测试,并且效果很好。我在控制台记录循环中的值,似乎正在发生的是数组中的每个单词都被记录下来,然后模式只为最后一个实例打开。不知道为什么

这里是 for each 循环:

words.forEach(function(word) {

      console.log(word);

      $('.modal-title').html("Edit value for "+word);
      $('#wordModal').modal('show');

      $('#submit').click(function() {

        let input = $('#elm2').val();

        newBody = body.replaceAll("["+word+"]", input);
        body = newBody;

        $('#wordModal').modal('hide');
      })
    });

当模态出现时,标题显示“输入(数组中的最后一个元素)的值”

我的目标:

对于数组中的每个元素,我希望屏幕上出现一个弹出窗口来更改它的值。为下一个元素加载另一个弹出窗口,依此类推。到目前为止,提示工作正常,但看起来不太好。

这是模态的代码:

<div class="modal fade" id="wordModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h4 class="modal-title">Edit Value</h4>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        </div>
        <div class="modal-body">

          <div class="form-group">
            <label>Comment</label>
            <textarea type="text" class="form-control" name="comment" id="elm2" placeholder=""></textarea>
          </div>
        </div>

        <div class="modal-footer">
          <button type="button" id="submit" class="btn btn-primary">Add</button>
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        </div>
      </div>
    </div>
  </div>

【问题讨论】:

  • 代码的行为完全符合其应有的方式。您正在循环并使相同的模型可见,因此它为每个单词更新了一个模型,因此您只能看到最后一个单词。您需要显示模式等待输入,然后在捕获第一个单词后显示第二个单词。
  • 模式与 javascript 提示或警报不同。提示和警报会暂停 javascript 的执行,直到用户单击按钮。模态只是 html。它不会停止 JavaScript。如果你想要相同的行为,你必须采取不同的方法。就像一个函数而不是一个循环。
  • 但是你为什么期望它一个接一个?我的意思是代码不会等待点击 click 方法只附加带有回调函数的监听器而已。然后处理下一个对象。在回调中的项目更改时,您应该使其更像链表。
  • 我不知道 modals 没有停止 javascript。有人有替代品的例子吗?
  • 并非没有更多上下文。评论没有足够的空间给你任何例子。除非他们回答您的问题,否则无法使用答案。一个随机的例子不是你问题的答案。您必须编辑您的问题,添加对您正在尝试做的事情的解释(我的意思是脚本为用户做了什么,而不是问题本身)并添加相关的 HTML 代码,以便我们给您一个答案这实际上会解决您的问题。

标签: javascript


【解决方案1】:

除了这可能不是最好的 UX 之外,使用 modals 执行此操作的方法是使用 async/await 将固有的异步操作转变为感觉更同步的东西:

function showModal(word){
 return new Promise(resolve => {
  $('.modal-title').html("Edit value for "+word);
  $('#wordModal').modal('show').on("hidden.bs.modal", function(){
     let input = $('#elm2').val();
     resolve(input);
  });
 });
}


async function promptAllWords(words){
   for(var i=0;i<words.length;i++){
      var word = words[i];
      var userResponse = await showModal(word);
      console.log("finished",word,"user typed:",userResponse);
   }
}

promptAllWords(["Hello","World","foo","bar"]);
 
 
 
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>

<div class="modal fade" id="wordModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h4 class="modal-title">Edit Value</h4>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        </div>
        <div class="modal-body">

          <div class="form-group">
            <label>Comment</label>
            <textarea type="text" class="form-control" name="comment" id="elm2" placeholder=""></textarea>
          </div>
        </div>

        <div class="modal-footer">
          <button type="button" id="submit" class="btn btn-primary" data-dismiss="modal">Add</button>
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        </div>
      </div>
    </div>
  </div>

正如您评论的那样,您想从 promptAllWords 返回一些东西,但它返回一个 Promise,您只需要像对待它一样对待它 - 一个异步调用。

async function promptAllWords(words){
   // fluff removed for brevity
   return "Test";
}

promptAllWords().then(result => {
    console.log("return value=",result);
});

【讨论】:

  • 谢谢,我应该把这个放在 for each 里面吗?
  • 不,您需要完全摆脱所有这些,并按照我在promptAllWords 方法中的示例使用标准的for 循环。
  • 谢谢!我意识到这不是对用户体验最友好的方式,但它现在可以让我通过
  • 我正在尝试让函数 promptAllWords 返回一个变量。但它返回一个承诺?我怎样才能从中获取变量?
  • @CíanMacTiarnáin 你希望它返回什么变量?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多