0

为什么这有效:

const details = document.querySelector('details')

document.getElementById("details1").addEventListener("toggle", event => {
  if (details1.open) {
    changeText1("open");
  } else {
    changeText1("closed");
  }
});

document.getElementById("details2").addEventListener("toggle", event => {
  if (details2.open) {
    changeText2("open");
  } else {
    changeText2("closed");
  };
});


function changeText1(status) {
 if(status == "open") {
    document.getElementById("p1").innerText = "opened";
    } else if (status == "closed") {
    document.getElementById("p1").innerText = "closed";
    }
} 

function changeText2(status) {
 if(status == "open") {
    document.getElementById("p2").innerText = "opened";
    } else if (status == "closed") {
    document.getElementById("p2").innerText = "closed";
    }
}
<html>
<body>
<details id="details1">
  <summary>#1</summary>text
</details>
<details id="details2">
  <summary>#2</summary>text
</details>

<p id="p1">not opened or closed</p>
<p id="p2">not opened or closed</p>

</body>
</html>

这是行不通的吗:

const details = document.querySelector('details')

function changeText(detailnr, status) {
 let pnr = "p" + detailnr; 
 if(status == "open") {
    document.getElementById(pnr).innerText = "opened";
    } else {
    document.getElementById(pnr).innerText = "closed";
    }
}

function maaklistner(detailsnr){
 let detailsid = "details" + detailsnr; 
 document.getElementById(detailsid).addEventListener("toggle", event => {
  if (detailsid.open) {
    changeText(detailsnr, "open");
  } else {
    changeText(detailsnr, "closed");
  } 
});
}


for(let i = 1; i < 3; i++){
 maaklistner(i); 
}
<html>
<body>
<details id="details1">
  <summary>#1</summary>text
</details>
<details id="details2">
  <summary>#2</summary>text
</details>

<p id="p1">not opened or closed</p>
<p id="p2">not opened or closed</p>

</body>
</html>

虽然代码本质上是完全重复的......

似乎事件侦听器本身已创建。但是,在 seconde 代码中没有正确处理 details.opened 语句,而在第一个代码中确实可以使用相同的方法。

有没有办法让第二种方法起作用?因为我需要创建超过 2000 个...

4

4 回答 4

2

它不起作用,因为您用于detailsid检查details元素是否打开。您需要使用包含 id 的元素detailsid

只需替换detailsid.opendocument.getElementById(detailsid).open.

这是一个有效的示例:

const details = document.querySelector('details')

function changeText(detailnr, status) {
  let pnr = "p" + detailnr;
  if (status == "open") {
    document.getElementById(pnr).innerText = "opened";
  } else {
    document.getElementById(pnr).innerText = "closed";
  }
}

function maaklistner(detailsnr) {
  let detailsid = "details" + detailsnr;
  
  document.getElementById(detailsid).addEventListener("toggle", event => {
    if (document.getElementById(detailsid).open) {
      changeText(detailsnr, "open");
    } else {
      changeText(detailsnr, "closed");
    }
  });
}


for (let i = 1; i < 3; i++) {
  maaklistner(i);
}
<details id="details1">
  <summary>#1</summary>text
</details>
<details id="details2">
  <summary>#2</summary>text
</details>

<p id="p1">not opened or closed</p>
<p id="p2">not opened or closed</p>

于 2022-01-24T20:32:17.633 回答
1

添加document.getElementById(detailsid)代替detailsid

const details = document.querySelector('details')

function changeText(detailnr, status) {
  let pnr = "p" + detailnr;
  if (status == "open") {
    document.getElementById(pnr).innerText = "opened";
  } else {
    document.getElementById(pnr).innerText = "closed";
  }
}

function maaklistner(detailsnr) {
  let detailsid = "details" + detailsnr;
  
  document.getElementById(detailsid).addEventListener("toggle", event => {
    if (document.getElementById(detailsid).open) {
      changeText(detailsnr, "open");
    } else {
      changeText(detailsnr, "closed");
    }
  });
}


for (let i = 1; i < 3; i++) {
  maaklistner(i);
}
<details id="details1">
  <summary>#1</summary>text
</details>
<details id="details2">
  <summary>#2</summary>text
</details>

<p id="p1">not opened or closed</p>
<p id="p2">not opened or closed</p>

于 2022-01-24T20:33:55.953 回答
1

我建议您在这里忘记唯一 ID...您可以details使用forEach循环为每个元素设置一个事件侦听器。

属性将保存文本更改目标data-*的索引(从零开始) 。p

看一看!它要简单得多。

// Get all the details elements
let details = document.querySelectorAll("details");

// Get an array from all the p elements
let stateIndicators = Array.from(document.querySelectorAll(".stateWrapper p"))

// For each details element, set an event listener
details.forEach(function(detail) {
  detail.addEventListener("toggle", function(e) {
  
    // Get its index from the data attribute
    let index = this.dataset.index
    
    // Change the text based on the open state
    stateIndicators[index].innerText = this.open ? "opened" : "closed"
  })
})
<html>

<body>
  <details data-index="0">
    <summary>#1</summary>text
  </details>
  <details data-index="1">
    <summary>#2</summary>text
  </details>
  <details data-index="2">
    <summary>#3</summary>text
  </details>
  <details data-index="3">
    <summary>#4</summary>text
  </details>
  <details data-index="4">
    <summary>#5</summary>text
  </details>

  <div class="stateWrapper"><!-- usefull wrapper here -->
    <p>not opened or closed</p>
    <p>not opened or closed</p>
    <p>not opened or closed</p>
    <p>not opened or closed</p>
    <p>not opened or closed</p>
  </div>

</body>

</html>

于 2022-01-24T20:46:26.660 回答
1

使用“点击”事件,因为“切换”不会冒泡。使用事件委托需要事件冒泡,它允许您添加单个事件处理程序来侦听事件以获取无限数量的标签,包括动态添加的标签。

const flipDetails = event => {
  const parent = event.currentTarget;
  const clicked = event.target;
  const nodes = [...parent.children];
  const log = document.querySelector('output');
  if (clicked !== parent && clicked.matches('summary')) {
    let dtl = clicked.parentElement;
    let pos = nodes.indexOf(dtl)+1;
    let status = dtl.open === true ? `${pos}: Closed` : `${pos}: Open`;
    log.innerHTML += '<br>'+ status;
  }
}

const main = document.querySelector('main');

main.addEventListener("click", flipDetails);

// For demo only
document.querySelector('output').insertAdjacentHTML('beforeBegin', `
    <details>
      <summary>Added Dynamically</summary>text
    </details>`);
output::before {content: 'Status: '}
<html>

<body>
  <main>
    <details>
      <summary>#1</summary>text
    </details>
    <details>
      <summary>#2</summary>text
    </details>
    <output></output>
  </main>
</body>

</html>

于 2022-01-24T21:30:09.927 回答