Javascript - 为 DOM 创建的元素创建切换函数

问题描述

我有一个按钮“-”,当点击它时,它会在我的“书籍”的角落创建一个“X”按钮来删除它们。有没有办法让它在我再次单击“-”按钮时在隐藏和显示“书籍”角落的“X”按钮之间切换?

没有JQuery,还没学会使用它

这是我的 HTML:

<div class="container">
<div class="book-display">
  <div class="title">Title:</div>
  <div class="author">Author:</div>
  <div class="pages">Pages:</div>
  <div class="read">Have Read:</div>
</div>
<div class="shelf"></div>
<div class="buttons">
  <button class="button" id="delete">➖</button>
  <button class="button" id="add">➕</button>
</div>

这是我的 Javascript:

 //Add Books to Shelf display
function addBookToShelf() {
    for (let i = 0; i < myLibrary.length; i++) {
        const books = document.createElement('div');
        books.classList.add('books');
        books.setAttribute('id',myLibrary[i].title)
        if (myLibrary[i].read === "Not Read") {
            books.style.background = "rgba(71,22,10,0.664)"
        };
        if (myLibrary[i].read === "Partially Read") {
            books.style.background = "rgba(199,199,58,0.575)"
        }
        const booksText = document.createElement('div');
        booksText.classList.add('book-text')
        booksText.addEventListener('click',() => {
            bookTitleEl.innerHTML = "Title: " + myLibrary[i].title;
            bookAuthorEl.innerHTML = "Author: " + myLibrary[i].author;
            bookPagesEl.innerHTML = "Pages: " + myLibrary[i].pages;
            bookReadEl.innerHTML = "Have Read: " + myLibrary[i].read;
        });
        booksText.innerHTML = myLibrary[i].title;
        shelfEl.appendChild(books);
        books.appendChild(booksText);
        document.getElementById(myLibrary[i].title).setAttribute('value',1);

        

//Add delete button to books function
function deleteXButton() {
    const deleteXEl = document.createElement('button');
    deleteXEl.classList.add('deleteX');
    books.appendChild(deleteXEl);
    
    deleteXEl.innerHTML = "X"
    document.getElementsByClassName('deleteX');
    if (document.getElementsByClassName('deleteX').length > myLibrary.length) {
    deleteXEl.remove();
    }
    if (deleteXEl.style.display === "block") {
        deleteXEl.style.display = "none";
      } else {
        deleteXEl.style.display = "block";
      }
    //Delete Book from Shelf & Object from Libray Array
    deleteXEl.addEventListener('click',() => {
        const bookIndex = myLibrary.indexOf(myLibrary[i])
        books.remove(delete myLibrary[bookIndex]);
        noBookFound();
    });
}

        //DELETE BUTTON EVENT LISTENER   
         deleteButtonEl.addEventListener('click',() => {
                deleteXButton();
        });
        }
      };

任何和所有帮助将不胜感激!

解决方法

classList API 有一个 toggle 方法,我们可以使用它来切换样式。如果您包含一个从 DOM 中删除元素的类(如 display: none),这将成为一种简单的方法来隐藏/显示您的元素以响应用户操作。您可以在代码段的 toggleDeleteButtons 函数中了解其工作原理。

我对您的代码进行了一系列其他建议修改,您可以根据自己的喜好随意选择或离开。顺便说一句,上面的链接指向 MDN,这是一个很好的网站,可以搜索任何不熟悉的网络开发术语(例如,您只需在谷歌上搜索“MDN findIndex”即可了解 {{1} } 数组的方法。)

findIndex
// Identifies some DOM elements globally
const
  deleteBooksButton = document.getElementById("delete"),addBookButton = document.getElementById("add"),shelfEl = document.getElementsByClassName("shelf")[0],deleteButtons = document.getElementsByClassName("delete-button");

// Declares the library globally,and populates it with sample books
let library;
library = getSampleLibrary(library);
addBooksToShelf(library);

// Calls toggleDeleteButtons when deleteBooksButton is clicked
deleteBooksButton.addEventListener("click",toggleDeleteButtons);

// Calls deleteBook when anything inside shelf is clicked
shelfEl.addEventListener("click",deleteBook);


// Defines function to show/hide all delete buttons
function toggleDeleteButtons(){
  for(let button of deleteButtons){
    button.classList.toggle("hidden");
  }
}


// Defines function to delete a book (Click events bubble up to `shelf`)
function deleteBook(event){
  // Makes sure the click event was on a delete-button before proceeding
  const clickedThing = event.target;
  if(!clickedThing.classList.contains("delete-button")){ return; }

  // Searches upward in DOM tree for bookEl,then downward for title
  const
    bookEl = clickedThing.closest(".book"),title = bookEl.querySelector(".title").textContent;

  // Removes bookEl from the DOM tree
  bookEl.remove();

  // Looks in library array for book object with matching title property
  const libraryIndex = library.findIndex(book => book.title == title);

  // Removes book object from library if there was a match
  if(libraryIndex > -1){
    library.splice(libraryIndex,1);
  }
}


// Defines function to populate shelf's DOM tree with book-related elements
function addBooksToShelf(library) {

  // Loops through elements of library array (referring to each as `book`)
  for (let book of library) {

    // Uses "destructuring" to get local variables bound to props of book
    const { title,author,pages,read } = book;

    // Creates bookEl and its descendants
      // bookEl will have 3 children: deleteDiv,teaserEl,and detailsEl
      // deleteDiv will have 1 child: deleteButton
      // detailsEl will have 4 div children (title,and read)
      //   (The 4 divs inside detailsEl will each have 1 span child)
    const
      bookEl = document.createElement("div"),// Will have class: "book"
      deleteDiv = document.createElement("div"),// ... "delete-div"
      teaserEl = document.createElement("div"),// ... "teaser" 
      detailsEl = document.createElement("div"),// ... "text"

      titleDiv = document.createElement("div"),authorDiv = document.createElement("div"),pagesDiv = document.createElement("div"),readDiv  = document.createElement("div"),titleSpan = document.createElement("span"),// ... "title" 
      authorSpan = document.createElement("span"),// ... "author"
      pagesSpan = document.createElement("span"),// ... "pages"
      readSpan  = document.createElement("span"); // ... "read"

    // Creates and configures deleteButton,and appends it to deleteDiv
    deleteButton = document.createElement("button");
    deleteButton.classList.add("delete-button");
    deleteButton.classList.add("hidden");
    deleteButton.textContent = "X";
    deleteDiv.appendChild(deleteButton);

    // Configures deleteDiv,and appends it to bookEl
    deleteDiv.classList.add("delete-div");
    bookEl.appendChild(deleteDiv);

    // Configures teaserEl,and appends it to bookEl
    teaserEl.innerHTML = title;
    teaserEl.classList.add("teaser"); // teaser class
    bookEl.appendChild(teaserEl);

    // Configures the spans
    titleSpan.classList.add("title");
    authorSpan.classList.add("author");
    pagesSpan.classList.add("pages");
    readSpan.classList.add("read");

    titleSpan.textContent = title;
    authorSpan.textContent = author;
    pagesSpan.textContent = pages;
    readSpan.textContent = read;

    // Populates divs (w/ label text and spans),and adds them to detailsEl
    titleDiv.innerHTML = "Title: " + titleSpan.outerHTML;
    authorDiv.innerHTML = "Author: " + authorSpan.outerHTML
    pagesDiv.innerHTML = "Pages: " + pagesSpan.outerHTML
    readDiv.innerHTML = "Have Read: " + readSpan.outerHTML

    detailsEl.appendChild(titleDiv);
    detailsEl.appendChild(authorDiv);
    detailsEl.appendChild(pagesDiv);
    detailsEl.appendChild(readDiv);

    // Configures detailsEl,and appends it to bookEl
    detailsEl.classList.add('text'); // text class
    detailsEl.classList.add("hidden"); // detailsEl & children are hidden
    bookEl.appendChild(detailsEl);

    // Configures bookEl (w/ styles,listener,etc),and adds it to shelf
    const
      readBG = "rgba(22,71,10,0.420)",notReadBG = "rgba(71,22,0.664)",partReadBG = "rgba(199,199,58,0.575)";
    if (read === "Partially Read") { bookEl.style.background = partReadBG; }
    else if (read === "Not Read") { bookEl.style.background = notReadBG; }
    else { bookEl.style.background = readBG; }

    bookEl.id = title; // (Careful: Book titles are not unique identifiers!)
    bookEl.classList.add("book");
    bookEl.setAttribute("data-value",1); // (Custom attributes use "data-")
    bookEl.addEventListener('click',toggleText); // Listener on book
    shelfEl.appendChild(bookEl);
  }
};


// Defines function to show text and hide teaser (or vice versa)
function toggleText(event){

  // Searches upward in DOM tree (from clicked element) to get closest book
  const bookEl = event.target.closest(".book");

  // Searches downward in DOM tree to find teaser & text,and update classes
  bookEl.querySelector(".teaser").classList.toggle("hidden");
  bookEl.querySelector(".text").classList.toggle("hidden");
}


// Defines function to return a sample library
function getSampleLibrary(library){
  const sampleLibrary = [
    {
      title: "Harry Potter and the Methods of Rationality",author: "Yudkowsky,Eliezer",pages: 750,read: "Read"
    },{
      title: "Go,Dog. Go!",author: "Eastman,P.D.",pages: 16,read: "Partially Read"
    }
  ];
  library = sampleLibrary;
  return library;
}
.shelf{ width: 350px; }
.book{ margin-top: 0.5em; padding: 0.5em; }
.delete-div{ text-align: right; } /* divs exist only to align buttons */
.delete-button{ border: 1px solid grey; border-radius: 0.3em; }
.hidden{ display: none; }