JavaScript DOM අංග සංස්කරණ ශ්රිතය නිෂ්ප්රයෝගිකව දෙවරක් යෙදීමේ දෝෂය
අපට යම් ලැයිස්තුවක් ඇතැයි සිතමු:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
ලැයිස්තුව සහ එහි අයිතම වෙනම විචල්යවලට ලබා ගනිමු:
let ul = document.querySelector('ul');
let lis = document.querySelectorAll('li');
අපගේ ලැයිස්තුවේ අයිතම ඇතුලත් කිරීමේ ක්ෂේත්රයක් පෙනෙන ආකාරයට සංස්කරණය කළ හැකි වන පරිදි කරමු:
for (let li of lis) {
li.addEventListener('click', function func() {
let input = document.createElement('input');
input.value = li.textContent;
li.textContent = '';
li.append(input);
input.addEventListener('blur', function() {
li.textContent = this.value;
li.addEventListener('click', func);
});
li.removeEventListener('click', func);
});
}
දැන් අපට අලුත් අයිතම ලැයිස්තුවට එකතු කළ හැකි වීමට අවශ්ය යැයි සිතමු. ඒ සඳහා ලැයිස්තුව යටතේ අදාළ ඇතුලත් කිරීමේ ක්ෂේත්රය අප සතුව ඇතැයි සිතමු:
<input id="adder">
මෙම ඇතුලත් කිරීමේ ක්ෂේත්රයට සබැඳියක් විචල්යයකට ලබා ගනිමු:
let adder = document.querySelector('#adder');
ඇතුලත් කිරීමේ ක්ෂේත්රයේ අවධානය අහිමි වූ විට ලැයිස්තුවට නව අයිතමයක් එකතු වන පරිදි අපගේ ඇතුලත් කිරීමේ ක්ෂේත්රයෙන් ගත් පාඨය සමඟ කරමු:
adder.addEventListener('blur', function() {
let li = document.createElement('li');
li.textContent = this.value;
ul.append(li);
});
දැන් අපට අවශ්ය වන්නේ නවවශයෙන් එකතු කරන ලද අයිතම ද සංස්කරණය කළ හැකි වීමයි. ඒවා සඳහා ස්වයංක්රීයව සංස්කරණය කිරීම ක්රියාත්මක නොවනු ඇත, එයට හේතුව ලැයිස්තු අයිතමවලට ක්ලික් ඉසව්ව සකස් කරන විට ඒ අයිතම තවම නොතිබීමයි.
මෙම ගැටලුව විසඳීම සඳහා විය හැකි විකල්ප සලකා බලමු.
පළමු විසඳුම
සරලම විසඳුම - func ශ්රිතයේ
කේතය නැවත ලිවීමයි,
එය නව සාදන ලද අයිතම සඳහාද
බැඳීම:
adder.addEventListener('blur', function() {
let li = document.createElement('li');
li.textContent = this.value;
li.addEventListener('click', function func() {
// මෙහිදී අපි කේතය නැවත ලියමු
});
ul.append(li);
});
ඇත්ත වශයෙන්ම, මෙම විසඳුමේ දී අපට වහාම අවාසිය දකින්නේ - කේතය නැවත ලිවීම නිවැරදි නොවේ.
දෙවන විසඳුම
නැවත ලිවීමේ ගැටලුව විසඳීම සඳහා
තර්කානුකූලව func ශ්රිතය
පිටතට ගෙන එය Function Declaration එකක්
බවට පත් කරන්න:
function func() {
let input = document.createElement('input');
input.value = li.textContent;
li.textContent = '';
li.append(input);
input.addEventListener('blur', function() {
li.textContent = this.value;
li.addEventListener('click', func);
});
li.removeEventListener('click', func);
}
මෙහිදී අපව ගැටලුවක් බලා සිටියි.
කාරණය නම් අපගේ ශ්රිතය පිටත
දෘෂ්ටි පරිසීමනයෙන් ලබාගත්
li විචල්යය භාවිතා කළ බවයි.
නමුත් ශ්රිතය පිටතට ගත් පසු මෙම
විචල්යය දැන් නොපෙනේ!
ගැටලුව විසඳීම සඳහා අපගේ
li පරාමිතියක් ලෙස යවමු:
function func(li) {
let input = document.createElement('input');
input.value = li.textContent;
li.textContent = '';
li.append(input);
input.addEventListener('blur', function() {
li.textContent = this.value;
li.addEventListener('click', func);
});
li.removeEventListener('click', func);
}
මෙහිදී අපගේ විසඳුම තවත් ගැටලුවක් ඇති කරයි. කාරණය නම් ඉසව්වක භාර ගන්නා අයෙකුට පරාමිතියක් යැවීම සරලව කළ නොහැකි බවයි:
for (let li in lis) {
li.addEventListener('click', func(li)); // ක්රියාත්මක නොවේ!
}
මෙම ගැටලුව විසඳීම සඳහා සරලව අනන්ය නාම භාර ගන්නා අයෙකු තුළ අපගේ ශ්රිතය කැඳවමු:
for (let li of lis) {
li.addEventListener('click', function() {
func(li);
});
}
ලැයිස්තුවේ නව අයිතමයක් සෑදීමේදීද ඒ හා සමාන ආකාරයට ක්රියා කරමු:
adder.addEventListener('blur', function() {
let li = document.createElement('li');
li.textContent = this.value;
li.addEventListener('click', function() {
func(li);
});
ul.append(li);
});
තෙවන විසඳුම
වඩාත් නිරවුල් විසඳුමක් පවතී. සරලව විධායකත්වය භාවිතා කළ හැකිය. මෙම අවස්ථාවේ දී නව ලැයිස්තු අයිතම සමඟ ගැටලුව පැන නොනගී:
ul.addEventListener('click', function(event) {
if (event.target.tagName === 'LI') { // li මත ක්ලික් කිරීම හරියටම අල්ලන්න, ඇතුලත් කිරීමේ ක්ෂේත්රය මත නොවේ
let li = event.target;
let input = document.createElement('input');
input.value = li.textContent;
li.textContent = '';
li.append(input);
input.addEventListener('blur', function() {
li.textContent = this.value;
});
}
});
මෙම අවස්ථාවේ දී ලැයිස්තු අයිතම හරහා ලූපය පොදුවේ අවශ්ය නොවන අතර, නව ලැයිස්තු අයිතමයක් සෑදීම සඳහා වන කේතය මෙය දක්වා අඩු වේ:
adder.addEventListener('blur', function() {
let li = document.createElement('li');
li.textContent = this.value;
ul.append(li);
});