javascript - 添加第二个元素后,第一个元素不会切换

标签 javascript

我创建了创建元素的函数

function createElements(value) {
  //Create div .toggler
  const toggler = document.createElement('div');
  toggler.classList.add('toggler');

  //Create div .content
  const content = document.createElement('div');
  content.classList.add('content');

  //Append div .toggler in div .container
  container.append(toggler);

  //Append div .content in div .container
  container.append(content);

  toggler.innerText = 'Click me';
  content.innerText = value;
}

如果我单击切换器“单击我”,则应显示和隐藏内容的函数

function toggleContent() {
  //Get created elements
  const togglers = document.querySelectorAll('.toggler'),
    contents = document.querySelectorAll('.content');

  //Toggle both div .active
  togglers.forEach((toggler, index) => {
    const content = contents[index];

    //Get div .content height
    const contentHeight = content.clientHeight + 'px';

    //Set div .content height
    content.style.height = '0px';

    //Toggle event
    toggler.addEventListener('click', () => {
      if (!toggler.classList.contains('active')) {
        toggler.classList.add('active');
      } else {
        toggler.classList.remove('active');
      }

      if (!content.classList.contains('active')) {
        content.classList.add('active');
        content.style.height = contentHeight;
      } else {
        content.classList.remove('active');
        content.style.height = '0px';
      }
    });
  });
}

将这两个函数放在按钮事件中

//Create html elements and set value inner them event
btn.addEventListener('click', () => {
  createElements(input.value);
  toggleContent();

  //Clear input value
  input.value = '';
  //   console.log(input.value);
});

一切正常,但如果我添加第二个元素,第一个元素切换器将不起作用

//Get html elements
const container = document.querySelector('.container'),
  input = document.querySelector('.input'),
  btn = document.querySelector('.btn');

function createElements(value) {
  //Create div .toggler
  const toggler = document.createElement('div');
  toggler.classList.add('toggler');

  //Create div .content
  const content = document.createElement('div');
  content.classList.add('content');

  //Append div .toggler in div .container
  container.append(toggler);

  //Append div .content in div .container
  container.append(content);

  toggler.innerText = 'Click me';
  content.innerText = value;
}

function toggleContent() {
  //Get created elements
  const togglers = document.querySelectorAll('.toggler'),
    contents = document.querySelectorAll('.content');

  //Toggle both div .active
  togglers.forEach((toggler, index) => {
    const content = contents[index];

    //Get div .content height
    const contentHeight = content.clientHeight + 'px';

    //Set div .content height
    content.style.height = '0px';

    //Toggle event
    toggler.addEventListener('click', () => {
      if (!toggler.classList.contains('active')) {
        toggler.classList.add('active');
      } else {
        toggler.classList.remove('active');
      }

      if (!content.classList.contains('active')) {
        content.classList.add('active');
        content.style.height = contentHeight;
      } else {
        content.classList.remove('active');
        content.style.height = '0px';
      }
    });
  });
}

//Create html elements and set value inner them event
btn.addEventListener('click', () => {
  createElements(input.value);
  toggleContent();

  //Clear input value
  input.value = '';
  //   console.log(input.value);
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.content {
  overflow: hidden;
}
    <input type="text" class="input" />
    <button class="btn">add</button>
    
    <div class="container">
      <!-- <div class="toggler"></div>
      <div class="content"></div> -->
    </div>

最佳答案

第一个切换器(以及添加更多元素后的后续切换器)由于以下两个原因而停止工作:

  1. 每次添加新元素时,都会向现有元素添加另一个点击监听器(因此,当添加第二个元素时,第一个元素会获得另一个点击监听器,这会导致稍后出现一些奇怪的情况)
  2. 每次为每个现有项目添加新元素时,您都会记住它们的 clientHeight,因此如果它们实际上处于折叠状态,您会将 0px 存储到 contentHeight 因此新的点击处理程序将始终使用 0px 来扩展状态高度。最好切换 display: nonedisplay: block (或者根据需要选择 inline 或 inline-block)

我将点击处理程序注册移至第一个函数,这样每个创建的元素仅获得一个点击处理程序。

我删除了 clientHeight/contentHeight 逻辑,只添加了一个 CSS 规则,以便 .content 项在 .active 时可见,否则不可见。 所以改变的是CSS中的这部分

.content {
  display: none;
}

.content.active {
   display: block;
}

我保留了这样的逻辑:当您添加新项目时,它将折叠所有现有项目。我认为这也是你的逻辑,但如果你不想要这样,请告诉我。

更改是在 JS 代码中

//Toggle both div .active
togglers.forEach((toggler, index) => {
    const content = contents[index];

    // I added this to keep the same logic you had before
    // if you would like to not collapse them, just remove the 2 lines
    toggler.classList.remove('active');
    content.classList.remove('active');
});

//Get html elements
const container = document.querySelector('.container'),
  input = document.querySelector('.input'),
  btn = document.querySelector('.btn');

function createElements(value) {
  //Create div .toggler
  const toggler = document.createElement('div');
  toggler.classList.add('toggler');

  //Create div .content
  const content = document.createElement('div');
  content.classList.add('content');

  //Append div .toggler in div .container
  container.append(toggler);

  //Append div .content in div .container
  container.append(content);

  toggler.innerText = 'Click me';
  content.innerText = value;

  toggler.addEventListener('click', () => {
      if (!toggler.classList.contains('active')) {
        toggler.classList.add('active');
      } else {
        toggler.classList.remove('active');
      }

      if (!content.classList.contains('active')) {
        content.classList.add('active');
      } else {
        content.classList.remove('active');
      }
    });
}

function toggleContent() {
  //Get created elements
  const togglers = document.querySelectorAll('.toggler'),
    contents = document.querySelectorAll('.content');

  //Toggle both div .active
  togglers.forEach((toggler, index) => {
    const content = contents[index];

    toggler.classList.remove('active');
    content.classList.remove('active');
  });
}

//Create html elements and set value inner them event
btn.addEventListener('click', () => {
  createElements(input.value);
  toggleContent();

  //Clear input value
  input.value = '';
  //   console.log(input.value);
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.content {
  display: none;
}

.content.active {
   display: block;
}
    <input type="text" class="input" />
    <button class="btn">add</button>
    
    <div class="container">
      <!-- <div class="toggler"></div>
      <div class="content"></div> -->
    </div>

关于javascript - 添加第二个元素后,第一个元素不会切换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70645958/

相关文章:

javascript - 使用Redux(Redux-Saga)的错误信息提示

javascript - Mongoose:改进 find() 和 count() 查询

javascript - 我如何使用 Ace Editor 使用 getvalue?

javascript - Javascript的跨浏览器正则表达式库,使用函数替换

javascript - Babeljs 中的 "loose"是什么意思?

javascript - 计数最小值使第一个字符和最后一个字符相等所需的操作数

javascript - Bootstrap 4 不更新弹出窗口的 onclick 属性

javascript - 使用 successfunc 的 jqGrid 内联编辑

javascript - onchange 事件值以编程方式更改

javascript - 将 yyyy-mm-dd 转换为星期二 25 日