Javascipt removeChild无法按预期工作

时间:2019-06-12 10:59:56

标签: javascript

我有一个代码,可在单击电影名称后获取角色名称和性别。此信息出现在模式窗口中,我的目标是每次关闭模式时都删除带有字符的HTML元素,因此,如果我选择另一部电影,则会出现新的字符集,而旧的字符已被删除。

问题是removeChild方法无法按预期工作。我尝试了各种变化,包括parentNode,但没有帮助。

这是代码:

window.addEventListener('DOMContentLoaded', function() {
  let btn = document.querySelector('.sw-btn');
  let content = document.querySelector('.content');
  let modal = document.querySelector('.modal');
  let modalBody = document.querySelector('.modal-body');
  let closeBtn = document.querySelector('.close-btn');
  let filmsList = document.createElement('ul');
  let charsList = document.createElement('ol');

  function getFilms() {
    axios.get('https://swapi.co/api/films/').then(res => {
      content.appendChild(filmsList);
      for (var i = 0; i < res.data.results.length; i++) {
        res.data.results.sort(function(a, b) {
          let dateA = new Date(a.release_date),
            dateB = new Date(b.release_date);
          return dateA - dateB;
        });

        (function updateFilms() {
          let addFilm = document.createElement('li');
          filmsList.appendChild(addFilm);

          let addFilmAnchor = document.createElement('a');
          let addFilmId = document.createElement('p');
          let addFilmCrawl = document.createElement('p');
          let addFilmDirector = document.createElement('p');
          let addFilmDate = document.createElement('p');

          addFilmAnchor.textContent = res.data.results[i].title;
          addFilmId.textContent = `Episode ID: ${res.data.results[i].episode_id}`;
          addFilmCrawl.textContent = `Episode description: ${res.data.results[i].opening_crawl}`;
          addFilmDirector.textContent = `Episode director: ${res.data.results[i].director}`;
          addFilmDate.textContent = `Episode release date: ${res.data.results[i].release_date}`;

          addFilm.append(addFilmAnchor, addFilmId, addFilmCrawl, addFilmDirector, addFilmDate);
        })();
      }
      let links = document.getElementsByTagName('a');
      for (let j = 0; j < links.length; j++) {
        links[j].onclick = function() {
          modal.style.display = 'block';
          modalBody.appendChild(charsList);
          let chars = res.data.results[j].characters;
          for (let k = 0; k < chars.length; k++) {
            const element = chars[k];
            axios.get(element).then(res => {
              let addChar = document.createElement('li');
              charsList.appendChild(addChar);
              let addCharName = document.createElement('p');
              let addCharGender = document.createElement('p');
              addCharName.textContent = `Character name: ${res.data.name}`;
              addCharGender.textContent = `Character gender: ${res.data.gender}`;
              addChar.append(addCharName, addCharGender);
            })
          }
          closeBtn.addEventListener('click', () => {
            modal.style.display = 'none';
            console.log(modalBody.childNodes[0]);
            // Problem is here
            modalBody.removeChild(modalBody.childNodes[0]);
          });
          window.addEventListener('click', (e) => {
            if (e.target == modal) {
              modal.style.display = 'none';
              console.log(modalBody.childNodes[0]);
              modalBody.removeChild(modalBody.childNodes[0]);
            }
          })
        }
      }
    }).catch(err => {
      console.log("An error occured");
    })
  };

  btn.addEventListener('click', getFilms);

  closeBtn.addEventListener('click', () => {
    modal.style.display = 'none';
  });
  window.addEventListener('click', (e) => {
    if (e.target == modal) {
      modal.style.display = 'none';
    }
  })
});
body {
  max-height: 100vh;
  padding: 0;
  margin: 0;
  font-family: Muli;
}

body::before {
  background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Star_Wars_Logo.svg/1200px-Star_Wars_Logo.svg.png') no-repeat center / cover;
  background-size: cover;
  content: "";
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -2;
  opacity: 0.1;
}

h1 {
  text-align: center;
  color: #660d41;
  font-size: 3em;
  margin-top: 10px;
  letter-spacing: 1px;
}

main {
  display: flex;
  align-items: center;
  flex-direction: column;
}

.content {
  max-width: 55%;
  overflow-y: scroll;
  max-height: 75vh;
}

.modal {
  display: none;
  position: fixed;
  z-index: 1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgba(0, 0, 0, 0.5);
}

.modal-content {
  background-color: #f4f4f4;
  margin: 20% auto;
  width: 40%;
  box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.2), 0 7px 20px 0 rgba(0, 0, 0, 0.2);
  animation: modalOpen 1s;
}

.modal-header {
  background: coral;
  padding: 15px;
  color: white;
  letter-spacing: 1px;
  position: relative;
}

.modal-header h2 {
  margin: 0;
}

.modal-body {
  padding: 10px 20px;
}

.close-btn {
  color: white;
  float: right;
  font-size: 30px;
  position: absolute;
  top: 0px;
  right: 10px;
}

.close-btn:hover,
.close-btn:focus {
  color: black;
  text-decoration: none;
  cursor: pointer;
  transition: all 0.4s ease-in;
}

ul {
  list-style-type: none;
  padding: 10px 20px;
}

li {
  border-bottom: 1px solid orangered;
  margin-bottom: 30px;
}

li:last-child {
  border-bottom: none;
  margin-bottom: 0;
}

a {
  font-size: 1.7em;
  color: #b907d9;
  cursor: pointer;
  margin-bottom: 10px;
}

p {
  font-size: 1.2rem;
  color: #0f063f;
  margin: 10px 0;
}

button {
  padding: .5em 1.5em;
  border: none;
  color: white;
  transition: all 0.2s ease-in;
  background: #da2417;
  border-radius: 20px;
  font-size: 1em;
  cursor: pointer;
  margin-top: 15px;
}

button:focus {
  outline: none;
}

button:hover {
  background: #e7736b;
}

button:active {
  box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.7) inset;
}

@keyframes modalOpen {
  from {
    opacity: 0
  }
  to {
    opacity: 1
  }
}
<link href="https://fonts.googleapis.com/css?family=Muli&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
<h1>Star wars films</h1>
<main>
  <div class="content"></div>
  <div class="modal">
    <div class="modal-content">
      <div class="modal-header">
        <span class="close-btn">&times;</span>
        <h2>Episode Characters</h2>
      </div>
      <div class="modal-body"></div>
    </div>
  </div>
  <button class="sw-btn">Find Films</button>
</main>

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

问题在于,在将字符追加到列表时,您使用的是相同的ol元素,因为您是在开始时实例化它并在以后重新使用它:let charsList = document.createElement('ol');

关闭模态时,将从模态中删除该ol元素,但不会删除其内容。再次打开模式时,将再次添加ol-您的旧内容。

如果将charsList的声明移到onclick处理程序中,它将起作用。

此外,您应该只注册一次模态的关闭处理程序。否则,它将在您打开模态时被调用。

演示:

window.addEventListener('DOMContentLoaded', function () {
    let btn = document.querySelector('.sw-btn');
    let content = document.querySelector('.content');
    let modal = document.querySelector('.modal');
    let modalBody = document.querySelector('.modal-body');
    let closeBtn = document.querySelector('.close-btn');
    let filmsList = document.createElement('ul');

    closeBtn.addEventListener('click', () => {
        modal.style.display = 'none';
        console.log(modalBody.childNodes[0]);
        modalBody.removeChild(modalBody.childNodes[0]);
    });
    
    window.addEventListener('click', (e) => {
        if (e.target == modal) {
            modal.style.display = 'none';
            console.log(modalBody.childNodes[0]);
            modalBody.removeChild(modalBody.childNodes[0]);
        }
    })

    function getFilms() {
        axios.get('https://swapi.co/api/films/').then(res => {
            content.appendChild(filmsList);
            for (var i = 0; i < res.data.results.length; i++) {
                res.data.results.sort(function (a, b) {
                    let dateA = new Date(a.release_date),
                        dateB = new Date(b.release_date);
                    return dateA - dateB;
                });

                (function updateFilms() {
                    let addFilm = document.createElement('li');
                    filmsList.appendChild(addFilm);

                    let addFilmAnchor = document.createElement('a');
                    let addFilmId = document.createElement('p');
                    let addFilmCrawl = document.createElement('p');
                    let addFilmDirector = document.createElement('p');
                    let addFilmDate = document.createElement('p');

                    addFilmAnchor.textContent = res.data.results[i].title;
                    addFilmId.textContent = `Episode ID: ${res.data.results[i].episode_id}`;
                    addFilmCrawl.textContent = `Episode description: ${res.data.results[i].opening_crawl}`;
                    addFilmDirector.textContent = `Episode director: ${res.data.results[i].director}`;
                    addFilmDate.textContent = `Episode release date: ${res.data.results[i].release_date}`;

                    addFilm.append(addFilmAnchor, addFilmId, addFilmCrawl, addFilmDirector, addFilmDate);
                })();
            }
            let links = document.getElementsByTagName('a');
            for (let j = 0; j < links.length; j++) {
                links[j].onclick = function () {
                    modal.style.display = 'block';
                    let charsList = document.createElement('ol');
                    modalBody.appendChild(charsList);
                    let chars = res.data.results[j].characters;
                    for (let k = 0; k < chars.length; k++) {
                        const element = chars[k];
                        axios.get(element).then(res => {
                            let addChar = document.createElement('li');
                            charsList.appendChild(addChar);
                            let addCharName = document.createElement('p');
                            let addCharGender = document.createElement('p');
                            addCharName.textContent = `Character name: ${res.data.name}`;
                            addCharGender.textContent = `Character gender: ${res.data.gender}`;
                            addChar.append(addCharName, addCharGender);
                        })
                    }
                }
            }
        }).catch(err => {
            console.log("An error occured");
        })
    };

    btn.addEventListener('click', getFilms);

    closeBtn.addEventListener('click', () => {
        modal.style.display = 'none';
    });
    window.addEventListener('click', (e) => {
        if (e.target == modal) {
            modal.style.display = 'none';
        }
    })
});
body {
  max-height: 100vh;
  padding: 0;
  margin: 0;
  font-family: Muli;
}

body::before {
  background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Star_Wars_Logo.svg/1200px-Star_Wars_Logo.svg.png') no-repeat center / cover;
  background-size: cover;
  content: "";
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -2;
  opacity: 0.1;
}

h1 {
  text-align: center;
  color: #660d41;
  font-size: 3em;
  margin-top: 10px;
  letter-spacing: 1px;
}

main {
  display: flex;
  align-items: center;
  flex-direction: column;
}

.content {
  max-width: 55%;
  overflow-y: scroll;
  max-height: 75vh;
}

.modal {
  display: none;
  position: fixed;
  z-index: 1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgba(0, 0, 0, 0.5);
}

.modal-content {
  background-color: #f4f4f4;
  margin: 20% auto;
  width: 40%;
  box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.2), 0 7px 20px 0 rgba(0, 0, 0, 0.2);
  animation: modalOpen 1s;
}

.modal-header {
  background: coral;
  padding: 15px;
  color: white;
  letter-spacing: 1px;
  position: relative;
}

.modal-header h2 {
  margin: 0;
}

.modal-body {
  padding: 10px 20px;
}

.close-btn {
  color: white;
  float: right;
  font-size: 30px;
  position: absolute;
  top: 0px;
  right: 10px;
}

.close-btn:hover,
.close-btn:focus {
  color: black;
  text-decoration: none;
  cursor: pointer;
  transition: all 0.4s ease-in;
}

ul {
  list-style-type: none;
  padding: 10px 20px;
}

li {
  border-bottom: 1px solid orangered;
  margin-bottom: 30px;
}

li:last-child {
  border-bottom: none;
  margin-bottom: 0;
}

a {
  font-size: 1.7em;
  color: #b907d9;
  cursor: pointer;
  margin-bottom: 10px;
}

p {
  font-size: 1.2rem;
  color: #0f063f;
  margin: 10px 0;
}

button {
  padding: .5em 1.5em;
  border: none;
  color: white;
  transition: all 0.2s ease-in;
  background: #da2417;
  border-radius: 20px;
  font-size: 1em;
  cursor: pointer;
  margin-top: 15px;
}

button:focus {
  outline: none;
}

button:hover {
  background: #e7736b;
}

button:active {
  box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.7) inset;
}

@keyframes modalOpen {
  from {
    opacity: 0
  }
  to {
    opacity: 1
  }
}
<link href="https://fonts.googleapis.com/css?family=Muli&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
<h1>Star wars films</h1>
<main>
  <div class="content"></div>
  <div class="modal">
    <div class="modal-content">
      <div class="modal-header">
        <span class="close-btn">&times;</span>
        <h2>Episode Characters</h2>
      </div>
      <div class="modal-body"></div>
    </div>
  </div>
  <button class="sw-btn">Find Films</button>
</main>

答案 1 :(得分:0)

在点击关闭按钮时执行charsList.innerText = '';

调用removeChild时,您会从UI的模态主体中删除<ol>。单击关闭按钮后,您会看到modalBody为空。

但是您已经通过<ol>let charsList = document.createElement('ol');元素存储在js变量中,因此ol元素本身实际上并没有改变。 <li>元素仍在<ol>内部。然后,您添加更多新的<li>并将其放回modalBody

enter image description here

我的解决方案是单击关闭按钮时删除<ol>中的所有元素。