先看這個固定例子
先註冊一個監聽器,深複製按鈕,再給副本獨立 ID。程式各點原件和副本一次。
<style>html{font-size:16px}body{margin:12px;font:1rem/1.5 system-ui,sans-serif;color:#17332d;background:#fff}p{overflow-wrap:anywhere}output{display:block;margin-block:12px;overflow-wrap:anywhere;white-space:pre-wrap}button,input{font:inherit;max-width:100%;box-sizing:border-box}button{margin:4px;padding:8px}label{display:block;margin-block:8px}button:focus-visible,input:focus-visible{outline:3px solid #23715d;outline-offset:2px}ul{padding-inline-start:24px}li{overflow-wrap:anywhere}.highlight{border:2px solid green}</style>
<button id="original" type="button"><span>原件</span></button><output id="result"></output>
<script>let count=0;const original=document.querySelector('#original');original.addEventListener('click',()=>count++);const copy=original.cloneNode(true);copy.id='copy';copy.querySelector('span').textContent='副本';original.after(copy);original.click();copy.click();
const result=count;
document.querySelector('#result').textContent=JSON.stringify(result);
console.log(JSON.stringify(result));
</script>1| 核對項目 | 所給輸入或動作 | 結果 |
|---|---|---|
| 原件點擊 | #original | count: 1 |
| 副本點擊 | #copy | count: 1 |
| ID | original / copy | 各自獨立 |
原生機制怎樣處理
cloneNode(true) 複製屬性及子節點,卻不複製 addEventListener 註冊的監聽器。ID 也要自己改,深複製不會自動產生獨立名稱。本例沒有內聯事件屬性,不能把這個結果擴大到那種寫法。
比較另一寫法
副本沿用 ID,便有兩個相同 ID,但監聽器仍沒有複製。外觀相似、deep=true,都不證明操作相同。
<style>html{font-size:16px}body{margin:12px;font:1rem/1.5 system-ui,sans-serif;color:#17332d;background:#fff}p{overflow-wrap:anywhere}output{display:block;margin-block:12px;overflow-wrap:anywhere;white-space:pre-wrap}button,input{font:inherit;max-width:100%;box-sizing:border-box}button{margin:4px;padding:8px}label{display:block;margin-block:8px}button:focus-visible,input:focus-visible{outline:3px solid #23715d;outline-offset:2px}ul{padding-inline-start:24px}li{overflow-wrap:anywhere}.highlight{border:2px solid green}</style>
<button id="original" type="button"><span>原件</span></button><output id="result"></output>
<script>let count=0;const original=document.querySelector('#original');original.addEventListener('click',()=>count++);const copy=original.cloneNode(true);original.after(copy);copy.click();
const result={duplicateIds:document.querySelectorAll('#original').length,count};
document.querySelector('#result').textContent=JSON.stringify(result);
console.log(JSON.stringify(result));
</script>{"duplicateIds":2,"count":0}試清邊界
新副本要有獨立點擊回呼,需另做甚麼?
查看參考答案
改成獨立 ID,再明確註冊監聽器。修正例子各點一次,各自計數器都是一。
<style>html{font-size:16px}body{margin:12px;font:1rem/1.5 system-ui,sans-serif;color:#17332d;background:#fff}p{overflow-wrap:anywhere}output{display:block;margin-block:12px;overflow-wrap:anywhere;white-space:pre-wrap}button,input{font:inherit;max-width:100%;box-sizing:border-box}button{margin:4px;padding:8px}label{display:block;margin-block:8px}button:focus-visible,input:focus-visible{outline:3px solid #23715d;outline-offset:2px}ul{padding-inline-start:24px}li{overflow-wrap:anywhere}.highlight{border:2px solid green}</style>
<button id="original" type="button"><span>原件</span></button><output id="result"></output>
<script>let originalCount=0,copyCount=0;const original=document.querySelector('#original');original.addEventListener('click',()=>originalCount++);const copy=original.cloneNode(true);copy.id='copy';copy.addEventListener('click',()=>copyCount++);original.after(copy);original.click();copy.click();
const result={originalCount,copyCount,spanCopied:copy.querySelectorAll('span').length,uniqueIds:new Set([original.id,copy.id]).size};
document.querySelector('#result').textContent=JSON.stringify(result);
console.log(JSON.stringify(result));
</script>{"originalCount":1,"copyCount":1,"spanCopied":1,"uniqueIds":2}