【问题标题】:setTimeout function not working : javascriptsetTimeout 函数不起作用:javascript
【发布时间】:2021-05-31 15:21:25
【问题描述】:

场景:刚刚创建了一个简单的图书列表应用,它可以接受一些输入并将其显示在 UI 上,并具有其他功能,例如使用 localStorage。

就像我添加了更多自定义警报一样(例如,显示警报 - 添加一本书, - 如果作者姓名包含数字等)整个警报内容已经离开。 (以前定义的警报之前工作正常)

也没有一个显示相似性的问题对我有用

处理页面中所有警报的方法

static showAlert(msg, className) {
        const alertBox = document.createElement('div');
        alertBox.className = `alert alert-${className} mb-3 p-2`;
        alertBox.appendChild(document.createTextNode(msg));

        const container = document.querySelector('.container');
        const form = document.querySelector('#book-form');

        // check whether if an alertBox already exist in the UI
        if(document.querySelector('.alert')) {
            // remove alertBox after some time
            setTimeout(() => {
                document.querySelector('.alert').remove();
            }, 3000);
        } else {
            container.insertBefore(alertBox, form);
        }
    }

这是我添加新的自定义警报的地方:

if(bookName === '' || authorName === '' || bookId === '') {
        Dom.showAlert('All fields are required', 'danger');
    } else if (!isNaN(bookName)) {
        Dom.showAlert('Name of the book should not contain numbers', 'danger');
        document.querySelector('#title').value = '';
    } else if (!isNaN(authorName)) {
        Dom.showAlert('Author Name should not contain numbers', 'danger');
        document.querySelector('#author').value = '';
    } else if (isNaN(bookId)) {
        Dom.showAlert('Reference Id should only consist of numbers', 'danger');
        document.querySelector('#bookId').value = '';

面临的问题:

快速说明:我已将 setTimeout 延迟设置为 3000

  1. 现有警报在 3 秒后未删除(之前效果很好)

  2. 如果需要在dom中存在另一个alert,那么应该删除之前显示的alert,并显示新的alert;即使这发生在 3 秒内。

我已将代码添加为 sn-p,因为我在设置 JSFiddle 时遇到了一些问题

// Book class 
class Book { 
    constructor(title, author, id) {
        this.bookName = title; 
        this.authorName = author; 
        this.bookId = id;
    }
}

// Dom class : handle user interface / dom
class Dom {
    static displayBooks() {
        //dummy data to mimic data in localStorage
        const savedBooks = [
            {
                bookName: 'Vikings',
                authorName: 'Michael Hirst',
                bookId: 9764363,
            },

            {
                bookName: 'The Soldier',
                authorName: 'David Gary',
                bookId: 5764363,
            },
        ]
        //const books = Store.getBooks();
        const books = savedBooks;
        books.forEach((book) => Dom.addBookToList(book))
    }

    static addBookToList(bookInfo) {
        const tbody = document.querySelector('#book-list')
        const bookRow = document.createElement('tr');
        bookRow.innerHTML = 
        `
        <tr>
            <td>${bookInfo.bookName}</td>
            <td>${bookInfo.authorName}</td>
            <td>${bookInfo.bookId}</td>
            <td><a href="#" class="btn btn-danger btn-sm deleteBtn">Delete</a></td>
        </tr>
        `
        tbody.appendChild(bookRow);
    }

    static deleteBook(target) {
        if(target.classList.contains('deleteBtn')) {
            target.parentElement.parentElement.remove()
            // show alert if user deletes a book
            Dom.showAlert('Book deleted successfully', 'warning');
        }
    }

    static showAlert(msg, className) {
        const alertBox = document.createElement('div');
        alertBox.className = `alert alert-${className} mb-3 p-2`;
        alertBox.appendChild(document.createTextNode(msg));

        const container = document.querySelector('.container');
        const form = document.querySelector('#book-form');

        // check whether if an alertBox already exist in the UI
        if(document.querySelector('.alert')) {
            // remove alerBox after an interval
            setTimeout(() => {
                document.querySelector('.alert').remove();
            }, 3000);
        } else {
            container.insertBefore(alertBox, form);
        }
    }

    static clearFields() {
        document.querySelector('#title').value = '';
        document.querySelector('#author').value = '';
        document.querySelector('#bookId').value = '';
    }
}


// Store class - deals with localStorage
/*class Store {
    static getBooks() {
        let books; 
        if(localStorage.getItem('books') === null) {
            // if there is no book in the localstorage, then we initialize an empty array (of objects);
            books = [];
        } else {
            // since the data is in the format of string, we need to change it to a javascript object in order to to things with it.Therefore we use JSON.parse
            books = JSON.parse(localStorage.getItem('books'));
        }

        return books;
    }

    static addBooks(book) {
        const books = Store.getBooks();
        books.push(book);

        localStorage.setItem('books', JSON.stringify(books))
    }

    static removeBooks(bookId) {
        const books = Store.getBooks();
        books.forEach((book, index) => {
            if(book.bookId === bookId) {
                books.splice(index, 1);
            }
        });

        localStorage.setItem('books', JSON.stringify(books));
    }
}*/


// Events in Dom 
document.addEventListener('DOMContentLoaded', Dom.displayBooks);

// Add new book to dom/ui
document.querySelector('#book-form').addEventListener('submit', event => {
    event.preventDefault();

    const bookName = document.querySelector('#title').value;
    const authorName = document.querySelector('#author').value;
    const bookId = document.querySelector('#bookId').value;

    // input validation
    if(bookName === '' || authorName === '' || bookId === '') {
        Dom.showAlert('All fields are required', 'danger');
    } else if (!isNaN(bookName)) {
        Dom.showAlert('Name of the book should not contain numbers', 'danger');
        document.querySelector('#title').value = '';
    } else if (!isNaN(authorName)) {
        Dom.showAlert('Author Name should not contain numbers', 'danger');
        document.querySelector('#author').value = '';
    } else if (isNaN(bookId)) {
        Dom.showAlert('Reference Id should only consist of numbers', 'danger');
        document.querySelector('#bookId').value = '';
    } else {
        // object instantiation of book
        const book = new Book(bookName, authorName, bookId);

        // Add submitted book to the list
        Dom.addBookToList(book);

        // Add Submitted bookk to the local Storage
        //Store.addBooks(book);

        // show alert after adding the book
        Dom.showAlert('Book added successfully', 'success');

        // Clear input fields after submitting
        Dom.clearFields();
    }
})


// Remove / Delete a book from the list
document.querySelector('#book-list')
.addEventListener('click', event => {
    // Remove book from the Dom
    Dom.deleteBook(event.target);

    // Remove book from the local storage
    //Store.removeBooks(event.target.parentElement.previousElementSibling.textContent);
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Book List app</title>
    <!-- fontAwesome script -->
    <script src="https://kit.fontawesome.com/39350fd9df.js"></script>
    <!-- bootstrap css -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" type="text/css">
</head>
<body>
    <div class="container mt-4">
        
        <h1 class="display-4 text-center mb-4"><i class="fas fa-book text-success"></i> <span class="text-success">BlueStock</span> <span class="text-muted">Book Shop</span></h1>

        <form action="#" id="book-form">
            <div class="form-group mb-2">
                <label for="title">Book Title</label>
                <input type="text" name="title" id="title" class="form-control">
            </div>
            <div class="form-group mb-2">
                <label for="author">Author Name</label>
                <input type="text" name="author" id="author" class="form-control">
            </div>
            <div class="form-group">
                <label for="book-id">Reference Id</label>
                <input type="text" name="title" id="bookId" class="form-control">
            </div>

            <input type="submit" value="Add Book" class="btn btn-primary w-100 mt-3" id="submit">
        </form>

        <table class="table table-striped mt-4">

            <thead>
                <tr>
                    <th>Book Title</th>
                    <th>Author Name</th>
                    <th>Reference Id</th>
                    <th class="text-warning"><small>Delete book</small></th>
                </tr>
            </thead>

            <tbody id="book-list"></tbody>
        </table>
    </div>

    <script src="app.js" type="text/javascript"></script>
</body>
</html>

【问题讨论】:

    标签: javascript function dom settimeout


    【解决方案1】:

    我注意到您的showAlert 的问题:

    showAlert(msg, className) {
        // ...
        if (document.querySelector('.alert')) {
            /*
            #1. At the first time this function called, this will always be null. Since '.alert' is not in the DOM yet (it wil be added to the DOM at the following 'else' block.
                Therefore, setTimeout here won't be called, since the code never enters here at the first time.
        
            #2. At the second time and forth, this will be called.
                However, it will not enter the `else` block which is to add the alert into the DOM
            */
            setTimeout(() => {
                document.querySelector('.alert').remove();
            }, 3000);
        
        } else {
            container.insertBefore(alertBox, form);
        }
    }
    

    如果我们将其分解为您的预期行为,代码可能应该是这样的;

    static showAlert(msg, className) {
        // If there's an existing alert, instantly remove it.
        if (document.querySelector('.alert')) {
            document.querySelector('.alert').remove();
        }
    
        // Create the alert
        const alertBox = document.createElement('div');
        alertBox.className = `alert alert-${className} mb-3 p-2`;
        alertBox.appendChild(document.createTextNode(msg));
    
        const container = document.querySelector('.container');
        const form = document.querySelector('#book-form');
    
        // Insert alert to the DOM.
        container.insertBefore(alertBox, form);
    
        // Remove the alert above after 3s
        setTimeout(() => {
            alertBox.remove();
        }, 3e3);
    }
    

    最终代码示例如下;

    // Book class 
    class Book {
      constructor(title, author, id) {
        this.bookName = title;
        this.authorName = author;
        this.bookId = id;
      }
    }
    
    // Dom class : handle user interface / dom
    class Dom {
      static displayBooks() {
        //dummy data to mimic data in localStorage
        const savedBooks = [{
            bookName: 'Vikings',
            authorName: 'Michael Hirst',
            bookId: 9764363,
          },
    
          {
            bookName: 'The Soldier',
            authorName: 'David Gary',
            bookId: 5764363,
          },
        ]
        //const books = Store.getBooks();
        const books = savedBooks;
        books.forEach((book) => Dom.addBookToList(book))
      }
    
      static addBookToList(bookInfo) {
        const tbody = document.querySelector('#book-list')
        const bookRow = document.createElement('tr');
        bookRow.innerHTML =
          `
            <tr>
                <td>${bookInfo.bookName}</td>
                <td>${bookInfo.authorName}</td>
                <td>${bookInfo.bookId}</td>
                <td><a href="#" class="btn btn-danger btn-sm deleteBtn">Delete</a></td>
            </tr>
            `
        tbody.appendChild(bookRow);
      }
    
      static deleteBook(target) {
        if (target.classList.contains('deleteBtn')) {
          target.parentElement.parentElement.remove()
          // show alert if user deletes a book
          Dom.showAlert('Book deleted successfully', 'warning');
        }
      }
    
      static showAlert(msg, className) {
        // If there's an existing alert, instantly remove it.
        if (document.querySelector('.alert')) {
          document.querySelector('.alert').remove();
        }
    
        // Create the alert
        const alertBox = document.createElement('div');
        alertBox.className = `alert alert-${className} mb-3 p-2`;
        alertBox.appendChild(document.createTextNode(msg));
    
        const container = document.querySelector('.container');
        const form = document.querySelector('#book-form');
    
        // Insert alert to the DOM.
        container.insertBefore(alertBox, form);
    
        // Remove the alert above after 3s
        setTimeout(() => {
            alertBox.remove();
        }, 3e3);
      }
    
      static clearFields() {
        document.querySelector('#title').value = '';
        document.querySelector('#author').value = '';
        document.querySelector('#bookId').value = '';
      }
    }
    
    
    // Store class - deals with localStorage
    /*class Store {
        static getBooks() {
            let books; 
            if(localStorage.getItem('books') === null) {
                // if there is no book in the localstorage, then we initialize an empty array (of objects);
                books = [];
            } else {
                // since the data is in the format of string, we need to change it to a javascript object in order to to things with it.Therefore we use JSON.parse
                books = JSON.parse(localStorage.getItem('books'));
            }
    
            return books;
        }
    
        static addBooks(book) {
            const books = Store.getBooks();
            books.push(book);
    
            localStorage.setItem('books', JSON.stringify(books))
        }
    
        static removeBooks(bookId) {
            const books = Store.getBooks();
            books.forEach((book, index) => {
                if(book.bookId === bookId) {
                    books.splice(index, 1);
                }
            });
    
            localStorage.setItem('books', JSON.stringify(books));
        }
    }*/
    
    
    // Events in Dom 
    document.addEventListener('DOMContentLoaded', Dom.displayBooks);
    
    // Add new book to dom/ui
    document.querySelector('#book-form').addEventListener('submit', event => {
      event.preventDefault();
    
      const bookName = document.querySelector('#title').value;
      const authorName = document.querySelector('#author').value;
      const bookId = document.querySelector('#bookId').value;
    
      // input validation
      if (bookName === '' || authorName === '' || bookId === '') {
        Dom.showAlert('All fields are required', 'danger');
      } else if (!isNaN(bookName)) {
        Dom.showAlert('Name of the book should not contain numbers', 'danger');
        document.querySelector('#title').value = '';
      } else if (!isNaN(authorName)) {
        Dom.showAlert('Author Name should not contain numbers', 'danger');
        document.querySelector('#author').value = '';
      } else if (isNaN(bookId)) {
        Dom.showAlert('Reference Id should only consist of numbers', 'danger');
        document.querySelector('#bookId').value = '';
      } else {
        // object instantiation of book
        const book = new Book(bookName, authorName, bookId);
    
        // Add submitted book to the list
        Dom.addBookToList(book);
    
        // Add Submitted bookk to the local Storage
        //Store.addBooks(book);
    
        // show alert after adding the book
        Dom.showAlert('Book added successfully', 'success');
    
        // Clear input fields after submitting
        Dom.clearFields();
      }
    })
    
    
    // Remove / Delete a book from the list
    document.querySelector('#book-list')
      .addEventListener('click', event => {
        // Remove book from the Dom
        Dom.deleteBook(event.target);
    
        // Remove book from the local storage
        //Store.removeBooks(event.target.parentElement.previousElementSibling.textContent);
      });
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Book List app</title>
      <!-- fontAwesome script -->
      <script src="https://kit.fontawesome.com/39350fd9df.js"></script>
      <!-- bootstrap css -->
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" type="text/css">
    </head>
    
    <body>
      <div class="container mt-4">
    
        <h1 class="display-4 text-center mb-4"><i class="fas fa-book text-success"></i> <span class="text-success">BlueStock</span> <span class="text-muted">Book Shop</span></h1>
    
        <form action="#" id="book-form">
          <div class="form-group mb-2">
            <label for="title">Book Title</label>
            <input type="text" name="title" id="title" class="form-control">
          </div>
          <div class="form-group mb-2">
            <label for="author">Author Name</label>
            <input type="text" name="author" id="author" class="form-control">
          </div>
          <div class="form-group">
            <label for="book-id">Reference Id</label>
            <input type="text" name="title" id="bookId" class="form-control">
          </div>
    
          <input type="submit" value="Add Book" class="btn btn-primary w-100 mt-3" id="submit">
        </form>
    
        <table class="table table-striped mt-4">
    
          <thead>
            <tr>
              <th>Book Title</th>
              <th>Author Name</th>
              <th>Reference Id</th>
              <th class="text-warning"><small>Delete book</small></th>
            </tr>
          </thead>
    
          <tbody id="book-list"></tbody>
        </table>
      </div>
    
      <script src="app.js" type="text/javascript"></script>
    </body>
    
    </html>

    【讨论】:

    • 这真的很好解释,也很容易理解。我试过了,是的,整个代码就像魅力一样。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-20
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多