เหตุใดการใช้ onClick () ใน HTML จึงเป็นการปฏิบัติที่ไม่ดี


133

ฉันเคยได้ยินมาหลายครั้งแล้วว่าการใช้เหตุการณ์ JavaScript เช่นonClick()ใน HTML เป็นการปฏิบัติที่ไม่ดีเพราะไม่ดีต่อความหมาย ฉันต้องการทราบว่าข้อเสียคืออะไรและจะแก้ไขโค้ดต่อไปนี้ได้อย่างไร?

<a href="#" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>


4
onlickc ไม่มีอะไรผิดปกติ แต่ด้วยการสร้าง href #ใครก็ตามที่เลือกปิดการใช้งานจาวาสคริปต์จะติดค้างและไม่สามารถทำอะไรได้ สำหรับบางเว็บไซต์นั่นเป็นสิ่งที่ดี แต่เพียงแค่เปิดหน้าต่างมันเป็นเรื่องโง่มากที่จะไม่ให้ลิงก์ "จริง"
Marc B

2
อ่านลิงค์นั้นแน่นอน มันมีส่วนเกี่ยวข้องกับความหมายน้อยมากและอีกมากมายที่เกี่ยวข้องกับ ... ทุกสิ่งในหน้านั้น :-)
morewry

ลองเปิดลิงค์ของคุณในแท็บใหม่แล้วคุณจะเห็นตัวอย่างว่าทำไมจึงผิด ...
Sebastien C.

2
นั่นควรเป็น<button>เพราะลิงก์ควรจะชี้ไปที่ทรัพยากรจริง วิธีนี้มีความหมายมากกว่าและชัดเจนมากขึ้นสำหรับผู้ใช้โปรแกรมอ่านหน้าจอ
programmer5000

คำตอบ:


172

คุณอาจกำลังพูดถึงJavascript ที่ไม่สร้างความรำคาญซึ่งจะมีลักษณะดังนี้:

<a href="#" id="someLink">link</a>

ด้วยตรรกะในไฟล์ javascript ส่วนกลางที่มีลักษณะดังนี้:

$('#someLink').click(function(){
    popup('/map/', 300, 300, 'map'); 
    return false;
});

ข้อดีคือ

  • พฤติกรรม (Javascript) ถูกแยกออกจากการนำเสนอ (HTML)
  • ไม่มีการผสมภาษา
  • คุณกำลังใช้กรอบงานจาวาสคริปต์เช่น jQuery ที่สามารถจัดการปัญหาข้ามเบราว์เซอร์ส่วนใหญ่ให้คุณได้
  • คุณสามารถเพิ่มลักษณะการทำงานให้กับองค์ประกอบ HTML จำนวนมากพร้อมกันได้โดยไม่ต้องทำซ้ำรหัส

30
คุณได้ระบุข้อดีไว้เล็กน้อย แต่ข้อเสียล่ะ? แก้จุดบกพร่องควันสีฟ้า?
abelito

2
@abelito: ไม่แน่ใจว่าการดีบักเป็นข้อเสีย หากมีข้อได้เปรียบในการดีบักเนื่องจากคุณสามารถก้าวผ่าน JavaScript ของคุณภายในเครื่องมือแก้ไขข้อบกพร่องของเบราว์เซอร์ ไม่แน่ใจว่าคุณสามารถทำได้อย่างง่ายดายหากรหัสอยู่ในบรรทัด a onClick. คุณยังสามารถเขียนการทดสอบหน่วยได้หากคุณต้องการต่อต้านสคริปต์ของคุณซึ่งยากมากเช่นกันฉันคิดว่าถ้ารหัสอยู่ภายในonClickและไม่มีตรรกะแยกออก โดยส่วนตัวแล้วฉันไม่มีปัญหาในการดีบัก JavaScript ที่ไม่สร้างความรำคาญและประโยชน์ในการจัดการและทดสอบโค้ด JavaScript นั้นดีมากที่จะไม่ใช้มัน
Nope

45
@ François Wahl: ข้อเสียเปรียบหลักคือความสามารถในการค้นพบ: การดู HTML ไม่ได้บอกคุณว่ามีการเรียกกลับใดที่แนบมาด้วย
Michael Borgwardt

1
@MichaelBorgwardt: ฉันเห็นด้วยกับคุณว่ามันเป็นข้อเสีย หากโค้ดมีโครงสร้างและจัดระเบียบที่ดีฉันไม่เห็นว่ามันเป็นปัญหาใหญ่เมื่อทำงานกับโปรเจ็กต์หรือดีบักฐานรหัสของคนอื่น โดยทั่วไปในขณะที่ฉันเห็นด้วยกับคุณฉันไม่เห็นว่าความสามารถในการค้นพบเป็นเหตุผลที่ดีในการเขียนสคริปต์ในบรรทัดผลประโยชน์ที่น่าเชื่อถือเช่นความสามารถในการทดสอบโค้ดและความสามารถในการแยกรหัสฟังก์ชัน / พฤติกรรมของคุณออกจาก DOM ฉันไม่ได้บอกว่ารหัสในบรรทัดไม่ดีและใช้ไม่ได้ ทำได้และดีอย่างแน่นอนขึ้นอยู่กับว่าคุณสนใจในสิ่งต่างๆเช่นความสามารถในการทดสอบหรือไม่
Nope

4
อีกประเด็นหนึ่งของการสนทนานี้กับสามเณร - onclickสามารถทำแผนที่ความสัมพันธ์เชิงสาเหตุระหว่างปฏิสัมพันธ์ขององค์ประกอบและเอฟเฟกต์ (การเรียกใช้ฟังก์ชัน) ได้อย่างชัดเจนมากขึ้นรวมทั้งลดภาระทางปัญญา บทเรียนจำนวนมากทำให้ผู้เรียนกลายเป็นเนื้อหาaddEventListenerที่รวบรวมแนวคิดอื่น ๆ ไว้ในไวยากรณ์ที่ยากขึ้น นอกจากนี้เฟรมเวิร์กที่ใช้องค์ประกอบล่าสุดเช่น Riot และ React ใช้onclickแอตทริบิวต์และกำลังเปลี่ยนแนวคิดเกี่ยวกับการแยกที่ควรจะเป็น การถ่ายโอนจาก HTML onclickไปยังองค์ประกอบที่สนับสนุนสิ่งนี้อาจเป็นกระบวนการ "ขั้นตอน" ที่มีประสิทธิภาพมากกว่าสำหรับการเรียนรู้
jmk2142

41

หากคุณใช้ jQuery แล้ว:

HTML:

 <a id="openMap" href="/map/">link</a>

JS:

$(document).ready(function() {
    $("#openMap").click(function(){
        popup('/map/', 300, 300, 'map');
        return false;
    });
});

สิ่งนี้มีประโยชน์ในการทำงานโดยไม่มี JS หรือหากผู้ใช้คลิกลิงก์ตรงกลาง

นอกจากนี้ยังหมายความว่าฉันสามารถจัดการป๊อปอัปทั่วไปได้โดยเขียนใหม่อีกครั้งเพื่อ:

HTML:

 <a class="popup" href="/map/">link</a>

JS:

$(document).ready(function() {
    $(".popup").click(function(){
        popup($(this).attr("href"), 300, 300, 'map');
        return false;
    });
});

สิ่งนี้จะช่วยให้คุณสามารถเพิ่มป๊อปอัปลงในลิงก์ใดก็ได้โดยเพียงแค่ให้คลาสป๊อปอัป

แนวคิดนี้สามารถขยายออกไปได้มากขึ้นเช่น:

HTML:

 <a class="popup" data-width="300" data-height="300" href="/map/">link</a>

JS:

$(document).ready(function() {
    $(".popup").click(function(){
        popup($(this).attr("href"), $(this).data('width'), $(this).data('height'), 'map');
        return false;
    });
});

ตอนนี้ฉันสามารถใช้รหัสบิตเดียวกันสำหรับป๊อปอัปจำนวนมากบนไซต์ทั้งหมดของฉันได้โดยไม่ต้องเขียนสิ่งที่ onclick! ใช่สำหรับการนำกลับมาใช้ใหม่!

นอกจากนี้ยังหมายความว่าหากในภายหลังฉันตัดสินใจว่าป๊อปอัปเป็นการปฏิบัติที่ไม่ดี (ซึ่งก็คือ!) และฉันต้องการแทนที่ด้วยหน้าต่างโมดอลสไตล์ไลท์บ็อกซ์ฉันสามารถเปลี่ยน:

popup($(this).attr("href"), $(this).data('width'), $(this).data('height'), 'map');

ถึง

myAmazingModalWindow($(this).attr("href"), $(this).data('width'), $(this).data('height'), 'map');

และป๊อปอัปทั้งหมดของฉันบนไซต์ทั้งหมดของฉันทำงานแตกต่างกันโดยสิ้นเชิง ฉันยังสามารถตรวจจับคุณสมบัติเพื่อตัดสินใจว่าจะทำอะไรในป๊อปอัปหรือจัดเก็บค่ากำหนดของผู้ใช้ว่าจะอนุญาตหรือไม่ ด้วยการคลิกแบบอินไลน์สิ่งนี้ต้องใช้ความพยายามอย่างมากในการคัดลอกและวาง


4
ทำงานโดยไม่ใช้ JavaScript ?? มันคือ jQuery มันต้องเปิดใช้งาน Javascript บนเบราว์เซอร์ถึงจะทำงานได้ใช่ไหม?
Thomas Shields

2
ได้ แต่ลิงก์สามารถเปลี่ยนเส้นทางไปยังหน้าที่ดำเนินการโดยไม่ใช้ JavaScript ได้ในกรณีนี้
ThiefMaster

12
การเชื่อมโยงทำงานโดยไม่ต้องใช้ JavaScript ดูว่าลิงก์มีแอตทริบิวต์ href ปกติอย่างไร หากผู้ใช้ไม่มี JavaScript ลิงก์จะยังคงเป็นลิงก์และผู้ใช้ยังสามารถเข้าถึงเนื้อหาได้
morewry

3
@Thomas Shields: ไม่เขาหมายความว่าถ้าคุณไม่มี Javascript ลิงค์จะยังคงพาคุณไปที่ / map / ...
Robert

2
อารวย! เราทุกคนรักคุณสำหรับทางออกที่ดีที่สุดนี้!
Nirmal

21

ด้วยแอปพลิเคชัน JavaScript ที่มีขนาดใหญ่มากโปรแกรมเมอร์กำลังใช้การห่อหุ้มโค้ดมากขึ้นเพื่อหลีกเลี่ยงการก่อมลพิษในขอบเขตทั่วโลก และเพื่อให้ฟังก์ชันพร้อมใช้งานสำหรับการดำเนินการ onClick ในองค์ประกอบ HTML ฟังก์ชันจะต้องอยู่ในขอบเขตส่วนกลาง

คุณอาจเคยเห็นไฟล์ JS ที่มีลักษณะเช่นนี้ ...

(function(){
    ...[some code]
}());

สิ่งเหล่านี้เป็นนิพจน์ฟังก์ชันที่เรียกใช้ทันที (IIFE) และฟังก์ชันใด ๆ ที่ประกาศภายในจะมีอยู่ภายในขอบเขตภายในเท่านั้น

หากคุณประกาศfunction doSomething(){}ภายใน IIFE ให้ทำการdoSomething()ดำเนินการ onClick ขององค์ประกอบในหน้า HTML ของคุณคุณจะได้รับข้อผิดพลาด

ในทางกลับกันถ้าคุณสร้าง eventListener สำหรับองค์ประกอบนั้นภายใน IIFE นั้นและโทรdoSomething()เมื่อผู้ฟังตรวจพบเหตุการณ์การคลิกคุณก็ทำได้ดีเพราะผู้ฟังและdoSomething()แบ่งปันขอบเขตของ IIFE

สำหรับเว็บแอปเล็ก ๆ น้อย ๆ ที่มีโค้ดเพียงเล็กน้อยก็ไม่สำคัญ แต่ถ้าคุณปรารถนาที่จะเขียนโค้ดเบสที่มีขนาดใหญ่และดูแลรักษาonclick=""ได้เป็นนิสัยที่คุณควรหลีกเลี่ยง


1
หากคุณต้องการเขียนโค้ดเบสขนาดใหญ่ที่ดูแลรักษาได้ให้ใช้เฟรมเวิร์ก JS เช่น Angular, Vue, React ... ซึ่งแนะนำให้ผูกตัวจัดการเหตุการณ์ไว้ในเทมเพลต HTML ของพวกเขา
Kamil Kiełczewski

20

ไม่ดีเนื่องจากสาเหตุหลายประการ:

  • มันผสมรหัสและมาร์กอัป
  • รหัสที่เขียนด้วยวิธีนี้จะต้องผ่าน eval
  • และทำงานในขอบเขตทั่วโลก

สิ่งที่ง่ายที่สุดคือการเพิ่มnameแอตทริบิวต์ให้กับ<a>องค์ประกอบของคุณจากนั้นคุณสามารถทำได้:

document.myelement.onclick = function() {
    window.popup('/map/', 300, 300, 'map');
    return false;
};

แม้ว่าแนวทางปฏิบัติที่ดีที่สุดในปัจจุบันคือการใช้idแทนชื่อและใช้addEventListener()แทนการใช้onclickเนื่องจากช่วยให้คุณสามารถผูกฟังก์ชันต่างๆเข้ากับเหตุการณ์เดียวได้


แม้แต่การแนะนำวิธีนี้ยังช่วยให้ผู้ใช้เกิดปัญหามากมายเกี่ยวกับการชนกันของตัวจัดการเหตุการณ์
รีแอคชั่น

3
@preaction เหมือนกับตัวจัดการเหตุการณ์แบบอินไลน์ดังนั้นทำไมคำตอบของฉันถึงบอกว่าใช้ดีกว่าaddEventListener()และทำไม
Alnitak

2
ใครช่วยอธิบายเพิ่มเติมได้ไหม "code ที่เขียนด้วยวิธีนี้จะต้องผ่าน eval" ... ฉันไม่พบสิ่งนี้ในเว็บ คุณกำลังบอกว่ามีข้อเสียด้านประสิทธิภาพหรือความปลอดภัยในการใช้ Javascript แบบอินไลน์หรือไม่?
MarsAndBack

12

มีสาเหตุสองสามประการ:

  1. ฉันพบว่ามันช่วยในการบำรุงรักษาเพื่อแยกมาร์กอัปเช่น HTML และสคริปต์ฝั่งไคลเอ็นต์ ตัวอย่างเช่นjQueryทำให้ง่ายต่อการเพิ่มตัวจัดการเหตุการณ์โดยใช้โปรแกรม

  2. ตัวอย่างที่คุณให้อาจใช้ไม่ได้ใน User Agent ที่ไม่รองรับ javascript หรือปิด javascript แนวคิดของการเพิ่มประสิทธิภาพแบบโปรเกรสซีฟจะส่งเสริมให้มีการเชื่อมโยงหลายมิติแบบธรรมดา/map/สำหรับตัวแทนผู้ใช้โดยไม่ต้องใช้จาวาสคริปต์จากนั้นเพิ่มตัวจัดการการคลิก prgramatically สำหรับตัวแทนผู้ใช้ที่สนับสนุนจาวาสคริปต์

ตัวอย่างเช่น:

มาร์กอัป:

<a id="example" href="/map/">link</a>

Javascript:

$(document).ready(function(){

    $("#example").click(function(){
        popup('/map/', 300, 300, 'map');
        return false;
    });

})

2
ขอบคุณที่เตือนฉันถึงการเพิ่มประสิทธิภาพที่ก้าวหน้าและสิ่งนี้ก็ยังคงเหมาะกับกระบวนทัศน์นั้นเช่นกัน:<a href="https://stackoverflow.com/map/" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
Daniel Sokolowski

10

การแก้ไข

วิธีการใช้ JavaScript ที่ไม่สร้างความรำคาญเป็นสิ่งที่ดีใน PAST โดยเฉพาะอย่างยิ่งการเชื่อมโยงตัวจัดการเหตุการณ์ใน HTML ถือเป็นการปฏิบัติที่ไม่ดี (ส่วนใหญ่เป็นเพราะonclick events run in the global scope and may cause unexpected errorสิ่งที่YiddishNinjaกล่าวถึง)

อย่างไรก็ตาม ...

ขณะนี้ดูเหมือนว่าแนวทางนี้จะล้าสมัยเล็กน้อยและต้องการการอัปเดต หากใครบางคนต้องการเป็นนักพัฒนาส่วนหน้ามืออาชีพและเขียนแอปที่มีขนาดใหญ่และซับซ้อนเขาจำเป็นต้องใช้เฟรมเวิร์กเช่น Angular, Vue.js เป็นต้นอย่างไรก็ตามเฟรมเวิร์กนั้นมักจะใช้ (หรืออนุญาตให้ใช้) เทมเพลต HTMLที่ตัวจัดการเหตุการณ์ถูกผูกไว้ ในโค้ดเทมเพลต html โดยตรงและมีประโยชน์ชัดเจนและมีประสิทธิภาพมากเช่นในเทมเพลตเชิงมุมมักจะเขียนว่า:

<button (click)="someAction()">Click Me</button> 

ใน js / html แบบ raw จะมีค่าเท่ากัน

<button onclick="someAction()">Click Me</button>

ความแตกต่างคือในonclickเหตุการณ์js ดิบจะถูกรันในขอบเขตส่วนกลาง แต่เฟรมเวิร์กจัดเตรียมการห่อหุ้ม

แล้วปัญหาอยู่ที่ไหน?

ปัญหาคือเมื่อโปรแกรมเมอร์มือใหม่ที่มักจะได้ยินว่า html-onclick นั้นไม่ดีและผู้ที่ใช้งานอยู่เสมอbtn.addEventListener("onclick", ... )ต้องการใช้เฟรมเวิร์กกับเทมเพลต ( addEventListenerมีข้อเสียเช่นกัน - หากเราอัปเดต DOM ในรูปแบบไดนามิกโดยใช้innerHTML=(ซึ่งค่อนข้างเร็ว ) - เราจะคลายเหตุการณ์ต่างๆ ตัวจัดการผูกในลักษณะนั้น) จากนั้นเขาจะต้องเผชิญกับบางสิ่งบางอย่างเช่นนิสัยที่ไม่ดีหรือแนวทางที่ไม่ถูกต้องในการใช้งานเฟรมเวิร์ก - และเขาจะใช้เฟรมเวิร์กในทางที่แย่มาก - เพราะเขาจะเน้นที่ js-part เป็นหลักและไม่มีในส่วนของเทมเพลต (และสร้างความไม่ชัดเจนและยากที่จะรักษา รหัส). ในการเปลี่ยนนิสัยนี้เขาจะเสียเวลามาก (และอาจต้องใช้โชคและครู)

ดังนั้นในความคิดของฉันจากประสบการณ์กับนักเรียนของฉันจะดีกว่าสำหรับพวกเขาถ้าพวกเขาใช้ html-handlers-bind ในตอนเริ่มต้น อย่างที่ฉันพูดมันเป็นเรื่องจริงที่ตัวจัดการจะถูกเรียกในขอบเขตทั่วโลก แต่ขั้นตอนนี้นักเรียนมักจะสร้างแอปพลิเคชันขนาดเล็กซึ่งง่ายต่อการควบคุม ในการเขียนแอปพลิเคชันที่ใหญ่ขึ้นพวกเขาเลือกเฟรมเวิร์กบางอย่าง

แล้วจะทำอย่างไร?

เราสามารถอัปเดตวิธีการ JavaScript ที่ไม่สร้างความรำคาญและอนุญาตตัวจัดการเหตุการณ์ที่เชื่อมโยง (ในที่สุดก็มีพารามิเตอร์อย่างง่าย) ใน html (แต่มีเพียงตัวจัดการการผูกเท่านั้น - ไม่ได้ใส่ตรรกะลงใน onclick เหมือนใน OP quesiton) ดังนั้นในความคิดของฉันใน raw js / html สิ่งนี้ควรได้รับอนุญาต

<button onclick="someAction(3)">Click Me</button>

หรือ

แต่ไม่ควรอนุญาตตัวอย่างด้านล่าง

<button onclick="console.log('xx'); someAction(); return true">Click Me</button>

<a href="#" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>

ความเป็นจริงเปลี่ยนไปมุมมองของเราก็ควรเช่นกัน


สวัสดีคามิลฉันเป็นผู้เริ่มต้นใช้งาน JavaScript และยังต้องเผชิญกับความสับสนในการใช้ onclick นั่นคือโปรดอธิบายข้อเสียของ onclick ดังต่อไปนี้: 1. คุณสามารถกำหนดเหตุการณ์แบบอินไลน์ได้เพียงรายการเดียว 2. เหตุการณ์อินไลน์จะถูกเก็บไว้เป็นคุณสมบัติขององค์ประกอบ DOM และเช่นเดียวกับคุณสมบัติของวัตถุทั้งหมดสามารถเขียนทับได้ 3. เหตุการณ์นี้จะเริ่มทำงานต่อไปแม้ว่าคุณจะลบคุณสมบัติ onclick
mirzhal

1
โฆษณา 1. มีเพียงคนเดียว แต่จากประสบการณ์ของผม (กับเชิงมุม) แสดงให้เห็นว่านี้เป็นพอในสถานการณ์ส่วนใหญ่ - addEventListenerแต่ถ้าไม่ได้แล้วเพียงแค่ใช้ โฆษณา 2. ใช่สามารถเขียนทับได้ (แต่โดยปกติจะไม่มีใครทำ) - ปัญหาอยู่ที่ไหน? โฆษณา 3 ตัวจัดการจะไม่ทำงานหลังจากลบ
แอตทริบิวต์

8

เป็นกระบวนทัศน์ใหม่ที่เรียกว่า " จาวาสคริปต์ที่ไม่สร้างความรำคาญ " "มาตรฐานเว็บ" ในปัจจุบันระบุว่าจะแยกฟังก์ชันการทำงานและการนำเสนอออกจากกัน

ไม่ใช่ "แนวทางปฏิบัติที่ไม่ดี" แต่เป็นเพียงมาตรฐานใหม่ส่วนใหญ่ที่ต้องการให้คุณใช้ตัวฟังเหตุการณ์แทน JavaScript แบบซับใน

นอกจากนี้นี่อาจเป็นเรื่องส่วนตัว แต่ฉันคิดว่ามันง่ายกว่ามากที่จะอ่านเมื่อคุณใช้ตัวฟังเหตุการณ์โดยเฉพาะอย่างยิ่งถ้าคุณมีคำสั่ง JavaScript มากกว่า 1 คำสั่งที่คุณต้องการเรียกใช้


2
หน้า Wikipedia ในหัวข้อนี้มีอายุมากกว่า 4 ปี ไม่ใช่กระบวนทัศน์ใหม่อีกต่อไป :)
Quentin

@David: มันอาจจะไม่ใช่ "ใหม่" แต่ก็ยังมีคนไม่ใช้มันจึง "ใหม่" สำหรับพวกเขา
Rocket Hazmat

6

คำถามของคุณจะทำให้เกิดการอภิปรายที่ฉันคิดว่า แนวคิดทั่วไปคือควรแยกพฤติกรรมและโครงสร้างออกจากกัน นอกจากนี้ afaik ตัวจัดการการคลิกแบบอินไลน์จะต้องevalนำไปสู่ ​​'กลายเป็น' ฟังก์ชันจาวาสคริปต์ที่แท้จริง และมันค่อนข้างเชย แต่นั่นเป็นข้อโต้แย้งที่ค่อนข้างสั่นคลอน อืมอ่านเกี่ยวกับเรื่องนี้@ quirksmode.org


ฉันไม่ต้องการสร้างสงครามศักดิ์สิทธิ์อีกครั้งฉันพยายามค้นหาความจริง: \
NiLL

2
  • เหตุการณ์ onclick ทำงานในขอบเขตส่วนกลางและอาจทำให้เกิดข้อผิดพลาดที่ไม่คาดคิด
  • การเพิ่มเหตุการณ์ onclick ไปยังองค์ประกอบ DOM จำนวนมากจะทำให้
    ประสิทธิภาพและประสิทธิภาพช้าลง

0

อีกสองเหตุผลที่ไม่ควรใช้เครื่องจัดการแบบอินไลน์:

พวกเขาอาจต้องการคำพูดที่น่าเบื่อหน่ายปัญหา

กำหนดสตริงที่กำหนดเองหากคุณต้องการสร้างตัวจัดการแบบอินไลน์ที่เรียกใช้ฟังก์ชันด้วยสตริงนั้นสำหรับวิธีแก้ปัญหาทั่วไปคุณจะต้องออกจากตัวคั่นแอตทริบิวต์ (ด้วยเอนทิตี HTML ที่เกี่ยวข้อง) และคุณจะ ต้องหลีกเลี่ยงตัวคั่นที่ใช้สำหรับสตริงภายในแอตทริบิวต์ดังต่อไปนี้:

const str = prompt('What string to display on click?', 'foo\'"bar');
const escapedStr = str
  // since the attribute value is going to be using " delimiters,
  // replace "s with their corresponding HTML entity:
  .replace(/"/g, '&quot;')
  // since the string literal inside the attribute is going to delimited with 's,
  // escape 's:
  .replace(/'/g, "\\'");
  
document.body.insertAdjacentHTML(
  'beforeend',
  '<button onclick="alert(\'' + escapedStr + '\')">click</button>'
);

มันน่าเกลียดอย่างไม่น่าเชื่อ จากตัวอย่างด้านบนหากคุณไม่ได้แทนที่'s จะทำให้เกิด SyntaxError เนื่องจากalert('foo'"bar')ไม่ใช่ไวยากรณ์ที่ถูกต้อง หากคุณไม่ได้แทนที่"s เบราว์เซอร์จะตีความว่าเป็นจุดสิ้นสุดของonclickแอตทริบิวต์ (คั่นด้วย"s ด้านบน) ซึ่งอาจไม่ถูกต้องเช่นกัน

หากคนหนึ่งใช้เครื่องจัดการแบบอินไลน์เป็นประจำเราต้องจำไว้ว่าทำสิ่งที่คล้ายกับข้างต้น (และทำถูกต้อง ) ทุกครั้งซึ่งน่าเบื่อและยากที่จะเข้าใจได้ในพริบตา ดีกว่าที่จะหลีกเลี่ยงตัวจัดการแบบอินไลน์โดยสิ้นเชิงเพื่อให้สามารถใช้สตริงที่กำหนดเองได้ในการปิดแบบง่ายๆ:

const str = prompt('What string to display on click?', 'foo\'"bar');
const button = document.body.appendChild(document.createElement('button'));
button.textContent = 'click';
button.onclick = () => alert(str);

ไม่ดีกว่านี้มากเหรอ?


ห่วงโซ่ขอบเขตของตัวจัดการแบบอินไลน์นั้นแปลกมาก

คุณคิดว่ารหัสต่อไปนี้จะบันทึกอะไร

let disabled = true;
<form>
  <button onclick="console.log(disabled);">click</button>
</form>

ลองใช้เรียกใช้ตัวอย่างข้อมูล อาจไม่ใช่สิ่งที่คุณคาดหวัง ทำไมมันถึงสร้างสิ่งที่มันทำ? เนื่องจากตัวจัดการแบบอินไลน์ทำงานภายในwithบล็อก รหัสด้านบนอยู่ภายในสาม withช่วงตึก: หนึ่งสำหรับdocumentหนึ่งสำหรับหนึ่งสำหรับ<form>และหนึ่งสำหรับ<button>:

ป้อนคำอธิบายภาพที่นี่

เนื่องจากdisabledเป็นคุณสมบัติของปุ่มการอ้างอิงdisabledภายในตัวจัดการแบบอินไลน์จะอ้างถึงคุณสมบัติของปุ่มไม่ใช่disabledตัวแปรภายนอก สิ่งนี้ค่อนข้างสวนทางกับธรรมชาติ withมีปัญหามากมาย: อาจเป็นที่มาของจุดบกพร่องที่สับสนและทำให้โค้ดช้าลงอย่างมาก ไม่อนุญาตเลยแม้แต่น้อยในโหมดเข้มงวด แต่ด้วยตัวจัดการแบบอินไลน์คุณจะถูกบังคับให้เรียกใช้โค้ดผ่านwiths - ไม่ใช่แค่ผ่านตัวเดียวwithแต่ต้องใช้หลายwithตัว มันบ้ามาก

withไม่ควรใช้ในโค้ด เนื่องจากตัวจัดการแบบอินไลน์ต้องการโดยปริยายwithพร้อมกับพฤติกรรมที่สับสนทั้งหมดจึงควรหลีกเลี่ยงตัวจัดการแบบอินไลน์เช่นกัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.