addEventListener vs onclick


705

ความแตกต่างระหว่างaddEventListenerและonclickคืออะไร

var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);

รหัสข้างต้นอยู่ร่วมกันในไฟล์. js แยกต่างหากและทำงานได้อย่างสมบูรณ์

คำตอบ:


959

ทั้งสองอย่างถูกต้อง แต่ไม่มีสิ่งใดที่ "ดีที่สุด" ต่อ se และอาจมีเหตุผลที่ผู้พัฒนาเลือกใช้ทั้งสองวิธี

Event Listeners (addEventListener และ attachEvent ของ IE)

Internet Explorer เวอร์ชันก่อนหน้าใช้งานจาวาสคริปต์ที่แตกต่างจากเบราว์เซอร์อื่น ๆ ด้วยรุ่นที่น้อยกว่า 9 คุณใช้วิธีattachEvent[ doc ] เช่นนี้:

element.attachEvent('onclick', function() { /* do stuff here*/ });

ในเบราว์เซอร์อื่น ๆ ส่วนใหญ่ (รวมถึง IE 9 ขึ้นไป) คุณใช้addEventListener[ doc ] เช่นนี้:

element.addEventListener('click', function() { /* do stuff here*/ }, false);

การใช้วิธีการนี้ ( เหตุการณ์ DOM ระดับ 2 ) คุณสามารถแนบจำนวนเหตุการณ์ได้ไม่ จำกัด ตามหลักเหตุผลกับองค์ประกอบเดียว ข้อ จำกัด เชิงปฏิบัติเพียงข้อเดียวคือหน่วยความจำฝั่งไคลเอ็นต์และข้อกังวลด้านประสิทธิภาพอื่น ๆ ซึ่งแตกต่างกันสำหรับแต่ละเบราว์เซอร์

ตัวอย่างข้างต้นแสดงถึงการใช้ฟังก์ชั่นที่ไม่ระบุชื่อ [ doc ] นอกจากนี้คุณยังสามารถเพิ่มฟังเหตุการณ์โดยใช้ฟังก์ชั่นอ้างอิง [ doc ] หรือปิด [ doc ]:

var myFunctionReference = function() { /* do stuff here*/ }

element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);

คุณสมบัติที่สำคัญอีกอย่างหนึ่งของaddEventListenerพารามิเตอร์สุดท้ายคือการควบคุมวิธีการที่ผู้ฟังตอบสนองต่อเหตุการณ์เดือดดาล [ doc ] ฉันได้ลองผิดลองถูกในตัวอย่างซึ่งเป็นมาตรฐานสำหรับกรณีการใช้งาน 95% ไม่มีอาร์กิวเมนต์ที่เทียบเท่าสำหรับattachEventหรือเมื่อใช้เหตุการณ์แบบอินไลน์

เหตุการณ์แบบอินไลน์ (HTML onclick = "" คุณสมบัติและ element.onclick)

ในเบราว์เซอร์ทั้งหมดที่รองรับจาวาสคริปต์คุณสามารถใส่ตัวฟังเหตุการณ์แบบอินไลน์ซึ่งมีความหมายในโค้ด HTML คุณอาจเคยเห็นสิ่งนี้:

<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>

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

วิธีอื่นที่คุณพูดถึง:

element.onclick = function () { /*do stuff here */ };

... เทียบเท่ากับจาวาสคริปต์แบบอินไลน์ยกเว้นว่าคุณสามารถควบคุมขอบเขตได้มากขึ้น (เนื่องจากคุณกำลังเขียนสคริปต์มากกว่า HTML) และสามารถใช้ฟังก์ชันที่ไม่ระบุชื่อการอ้างอิงฟังก์ชันและ / หรือการปิด

ข้อเสียเปรียบที่สำคัญกับเหตุการณ์แบบอินไลน์คือการที่แตกต่างจากผู้ฟังเหตุการณ์ที่อธิบายไว้ข้างต้นคุณอาจได้รับมอบหมายเหตุการณ์แบบอินไลน์เพียงครั้งเดียว เหตุการณ์แบบอินไลน์จะถูกจัดเก็บเป็นคุณลักษณะ / คุณสมบัติขององค์ประกอบ [ doc ] ซึ่งหมายความว่าสามารถเขียนทับได้

ใช้ตัวอย่าง<a>จาก HTML ด้านบน:

var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };

... เมื่อคุณคลิกที่องค์ประกอบคุณจะเห็นเฉพาะ "สิ่งที่ # 2" - คุณเขียนทับคุณสมบัติแรกที่ได้รับมอบหมายonclickด้วยค่าที่สองและคุณเขียนทับonclickคุณสมบัติHTML แบบอินไลน์ต้นฉบับด้วย ตรวจสอบออกที่นี่: http://jsfiddle.net/jpgah/

พูดกว้างไม่ได้ใช้เหตุการณ์แบบอินไลน์ อาจมีกรณีการใช้งานเฉพาะสำหรับมัน แต่ถ้าคุณไม่แน่ใจ 100% ว่าคุณมีกรณีการใช้งานนั้นคุณไม่ควรใช้และไม่ควรใช้เหตุการณ์แบบอินไลน์

Javascript สมัยใหม่ (เชิงมุมและที่คล้ายกัน)

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

<button (click)="doSomething()">Do Something</button>

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

ไหนดีที่สุด

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

jQuery และเฟรมเวิร์ก javascript อื่น ๆ ห่อหุ้มการใช้งานเบราว์เซอร์ที่แตกต่างกันของเหตุการณ์ DOM ระดับ 2 ในรุ่นทั่วไปเพื่อให้คุณสามารถเขียนรหัสที่สอดคล้องกับเบราว์เซอร์โดยไม่ต้องกังวลเกี่ยวกับประวัติของ IE ในฐานะกบฏ รหัสเดียวกันกับ jQuery เบราว์เซอร์ทั้งหมดและพร้อมที่จะเขย่า:

$(element).on('click', function () { /* do stuff */ });

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

function addEvent(element, evnt, funct){
  if (element.attachEvent)
   return element.attachEvent('on'+evnt, funct);
  else
   return element.addEventListener(evnt, funct, false);
}

// example
addEvent(
    document.getElementById('myElement'),
    'click',
    function () { alert('hi!'); }
);

ลองทำดู: http://jsfiddle.net/bmArj/

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

เอกสารและการอ่านที่เกี่ยวข้อง


14
ขออภัยที่จะชน แต่เพียงต้องการให้รุ่นที่ย่อของฟังก์ชั่นของคุณ (ซอ: jsfiddle.net/bmArj/153 ) -function addEvent(element, myEvent, fnc) { return ((element.attachEvent) ? element.attachEvent('on' + myEvent, fnc) : element.addEventListener(myEvent, fnc, false)); }
Deryck

10
@Gaurav_soni ไม่ชื่อของฟังก์ชั่นและรหัสทั้งหมดที่มีอยู่จะถูกเปิดเผยในไฟล์ javascript ซึ่งอยู่ในรูปแบบธรรมดา ทุกคนสามารถเปิดเว็บคอนโซลและดำเนินการหรือจัดการกับจาวาสคริปต์ใด ๆ หากจาวาสคริปต์ของคุณมีสิ่งใดที่อาจมีความเสี่ยงด้านความปลอดภัยหากมีการเปิดเผยต่อสาธารณะแสดงว่าคุณมีปัญหาที่สำคัญเนื่องจากมีการเปิดเผยต่อสาธารณะแล้ว
Chris Baker

4
ตราบใดที่เรามีการย่ออัลกอริธึมนี้เราก็อาจดำเนินต่อไปได้: function addEvent(e,n,f){return e.attachEvent?e.attachEvent('on'+n,f):e.addEventListener(n,f,!!0)}<< ที่ 98 ตัวอักษรตัวนี้เล็กกว่า 40%!
เทรเวอร์

3
@ เทรเวอร์ออกมาจากความอยากรู้ว่าทำไม !! 0? ทำไมไม่ 1 หรือเพียงแค่ 0
Chris Baker

2
@AdrianMoisa คำตอบนี้ถูกเขียนขึ้นเมื่อ AngularJS เป็นสิ่งใหม่ที่เพิ่มขึ้นและการปฏิบัติทั่วไปยังคงเป็น "การเพิ่มประสิทธิภาพที่ก้าวหน้า" - นั่นคือการเขียนเอกสาร HTML ในลักษณะที่จะทำงานร่วมกับหรือไม่ใช้จาวาสคริปต์ ในมุมมองนั้นการเชื่อมโยงเหตุการณ์จากจาวาสคริปต์จะเป็นการปฏิบัติที่ดีที่สุด ทุกวันนี้ฉันไม่คิดว่าหลายคนกังวลมากเกินไปเกี่ยวกับการปรับปรุงที่ก้าวหน้าโดยเฉพาะอย่างยิ่งไม่พิจารณาความชุกของสิ่งต่าง ๆ เช่นแองกูลาร์ ยังคงมีการแยกข้อโต้แย้งเกี่ยวกับเหตุการณ์แบบอินไลน์ (ไม่ใช้ Angular) แต่ก็มีสไตล์มากกว่าเนื้อหา
Chris Baker

193

ความแตกต่างที่คุณสามารถดูได้ถ้าคุณมีฟังก์ชั่นอีกสองอย่าง

var h = document.getElementById('a');
h.onclick = doThing_1;
h.onclick = doThing_2;

h.addEventListener('click', doThing_3);
h.addEventListener('click', doThing_4);

ฟังก์ชั่น 2, 3 และ 4 ทำงาน แต่ 1 ไม่ได้ นี่เป็นเพราะaddEventListenerไม่ได้เขียนทับตัวจัดการเหตุการณ์ที่มีอยู่ในขณะที่onclickแทนที่onclick = fnตัวจัดการเหตุการณ์ที่มีอยู่ใด ๆ

แน่นอนความแตกต่างที่สำคัญอื่น ๆ ก็คือมันonclickจะใช้งานได้ตลอดเวลา แต่addEventListenerจะไม่ทำงานใน Internet Explorer ก่อนรุ่น 9 คุณสามารถใช้แบบอะนาล็อกattachEvent(ซึ่งมีไวยากรณ์แตกต่างกันเล็กน้อย ) ใน IE <9


18
นั่นเป็นคำอธิบายที่ชัดเจนมาก! ขวาไปที่จุด ดังนั้นหากฉันต้องการฟังก์ชั่นหลายอย่างสำหรับเหตุการณ์หนึ่งฉันติดอยู่กับ addEventListener และฉันต้องเขียนโค้ดเพิ่มเติมสำหรับ attachEvent เพื่อรองรับ IE
William Sham

4
2, 3 และ 4 ควรตั้งชื่อ dosomething 1 ถูกแทนที่โดย 2 และไม่เคยถูกเรียก
DragonLord

แน่นอนคำอธิบายที่ชัดเจนมากและตรงประเด็น ไม่ว่าจะเป็นการเหมาะสมกว่าที่จะตั้งชื่อฟังก์ชั่น 'doThing_1' ฯลฯ (หากคุณยังต้องการรองรับ IE <9 ดูคำตอบของ Chris)
Frank Conijn

61

ในคำตอบนี้ฉันจะอธิบายสามวิธีในการกำหนดตัวจัดการเหตุการณ์ DOM

element.addEventListener()

ตัวอย่างรหัส:

element.addEventListener() มีข้อดีหลายประการ:

  • ช่วยให้คุณสามารถลงทะเบียนได้ไม่ จำกัดelement.removeEventListener()ไสเหตุการณ์และลบพวกเขาด้วย
  • มีuseCaptureพารามิเตอร์ซึ่งบ่งชี้ว่าคุณต้องการที่จะจัดการกับเหตุการณ์ของการจับภาพหรือเฟสเดือดปุดดู: ไม่เข้าใจแอตทริบิวต์ useCapture ใน addEventListener
  • ใส่ใจเกี่ยวกับความหมาย โดยทั่วไปจะทำให้การลงทะเบียนตัวจัดการเหตุการณ์ชัดเจนยิ่งขึ้น สำหรับผู้เริ่มต้นการเรียกใช้ฟังก์ชันทำให้เห็นได้ชัดว่ามีบางอย่างเกิดขึ้นในขณะที่การกำหนดเหตุการณ์ให้กับคุณสมบัติขององค์ประกอบ DOM อย่างน้อยก็ไม่ง่ายนัก
  • ช่วยให้คุณสามารถโครงสร้างเอกสารแยกต่างหาก (HTML) และตรรกะ (จาวาสคริปต์) ในการใช้งานเว็บเล็ก ๆ มันอาจจะไม่ดูเหมือนจะสำคัญ แต่มันไม่เรื่องกับโครงการใด ๆ ที่ใหญ่กว่า มันง่ายกว่ามากในการดูแลโครงการที่แยกโครงสร้างและตรรกะออกจากโครงการที่ไม่ได้ทำ
  • กำจัดความสับสนด้วยชื่อเหตุการณ์ที่ถูกต้อง เนื่องจากการใช้ฟังเหตุการณ์แบบอินไลน์หรือการกำหนดฟังเหตุการณ์ที่.oneventคุณสมบัติขององค์ประกอบ DOM จำนวนมากของการเขียนโปรแกรมจาวาสคริปต์ที่ไม่มีประสบการณ์คิดว่าชื่อเหตุการณ์เป็นตัวอย่างหรือonclick คือไม่ได้เป็นส่วนหนึ่งของชื่อเหตุการณ์ ชื่อเหตุการณ์ที่ถูกต้องและและว่าเป็นวิธีที่ชื่อเหตุการณ์จะถูกส่งผ่านไปยังonloadonclickload.addEventListener()
  • ทำงานในเกือบทุกเบราว์เซอร์ หากคุณยังได้ให้การสนับสนุน IE <= 8 คุณสามารถใช้polyfill จาก MDN

element.onevent = function() {}(เช่นonclick, onload)

ตัวอย่างรหัส:

นี่เป็นวิธีการลงทะเบียนตัวจัดการเหตุการณ์ใน DOM 0 ตอนนี้หมดกำลังใจเพราะ:

  • ช่วยให้คุณสามารถลงทะเบียนตัวจัดการเหตุการณ์เดียวเท่านั้น การลบตัวจัดการที่กำหนดออกมานั้นไม่ใช่วิธีที่ใช้งานง่ายเนื่องจากการลบตัวจัดการเหตุการณ์ที่กำหนดโดยใช้วิธีนี้คุณต้องเปลี่ยนoneventคุณสมบัติกลับไปเป็นสถานะเริ่มต้น (เช่นnull)
  • ไม่ตอบสนองต่อข้อผิดพลาดอย่างเหมาะสม ตัวอย่างเช่นหากคุณกำหนดสตริงให้กับข้อผิดพลาดwindow.onloadตัวอย่างเช่น: window.onload = "test";จะไม่ทำให้เกิดข้อผิดพลาดใด ๆ รหัสของคุณใช้งานไม่ได้และมันยากมากที่จะหาสาเหตุ .addEventListener()แต่จะโยนความผิดพลาด (อย่างน้อยใน Firefox): TypeError: อาร์กิวเมนต์ที่ 2 ของ EventTarget.addEventListener ไม่ได้เป็นวัตถุ
  • ไม่ได้ให้วิธีการเลือกหากคุณต้องการจัดการเหตุการณ์ในเฟสการจับภาพหรือเดือด

เครื่องมือจัดการเหตุการณ์แบบอินไลน์ ( oneventแอตทริบิวต์ HTML)

ตัวอย่างรหัส:

ในทำนองเดียวกันelement.oneventมันก็หมดกำลังใจ นอกเหนือจากปัญหาที่element.oneventมี:

  • เป็นปัญหาด้านความปลอดภัยที่อาจเกิดขึ้นเพราะจะทำให้ XSS เป็นอันตรายมากขึ้น ทุกวันนี้เว็บไซต์ควรส่งContent-Security-Policyส่วนหัว HTTP ที่เหมาะสมเพื่อบล็อกสคริปต์แบบอินไลน์และอนุญาตสคริปต์ภายนอกจากโดเมนที่เชื่อถือได้เท่านั้น ดูนโยบายความปลอดภัยของเนื้อหาทำงานอย่างไร
  • ไม่ได้โครงสร้างเอกสารแยกต่างหากและตรรกะ
  • หากคุณสร้างหน้าของคุณด้วยสคริปต์ฝั่งเซิร์ฟเวอร์และตัวอย่างเช่นคุณสร้างลิงก์เป็นร้อยลิงก์แต่ละอันมีตัวจัดการเหตุการณ์แบบอินไลน์เดียวกันรหัสของคุณจะยาวกว่าหากกำหนดตัวจัดการเหตุการณ์เพียงครั้งเดียว นั่นหมายความว่าลูกค้าจะต้องดาวน์โหลดเนื้อหาเพิ่มเติมและทำให้เว็บไซต์ของคุณช้าลง

ดูสิ่งนี้ด้วย


22

แม้ว่าจะonclickใช้ได้กับทุกเบราว์เซอร์ แต่addEventListenerไม่สามารถใช้งานได้ใน Internet Explorer เวอร์ชันเก่าซึ่งใช้attachEventแทน

ข้อเสียonclickคือสามารถมีตัวจัดการเหตุการณ์ได้เพียงคนเดียวในขณะที่อีกสองคนจะใช้การเรียกกลับที่ลงทะเบียนไว้ทั้งหมด


12

เท่าที่ฉันรู้เหตุการณ์ "โหลด" DOM ​​ยังคงทำงานได้ จำกัด มาก นั่นหมายความว่ามันจะยิงสำหรับwindow object, imagesและ<script>องค์ประกอบเช่น เช่นเดียวกันสำหรับการonloadกำหนดโดยตรง ไม่มีความแตกต่างทางเทคนิคระหว่างสองสิ่งนี้ อาจ.onload =มีความได้เปรียบข้ามเบราว์เซอร์ที่ดีขึ้น

อย่างไรก็ตามคุณไม่สามารถกำหนดload eventให้เป็น<div>หรือ<span>องค์ประกอบหรือ whatnot


9

สรุป:

  1. addEventListenerสามารถเพิ่มหลายเหตุการณ์ในขณะที่onclickสิ่งนี้ไม่สามารถทำได้
  2. onclickสามารถเพิ่มเป็นHTMLแอตทริบิวต์ได้ในขณะที่addEventListenerสามารถเพิ่มได้ภายใน<script>องค์ประกอบเท่านั้น
  3. addEventListener สามารถใช้อาร์กิวเมนต์ที่สามซึ่งสามารถหยุดการเผยแพร่เหตุการณ์

ทั้งสองสามารถใช้เพื่อจัดการเหตุการณ์ อย่างไรก็ตามaddEventListenerควรเป็นตัวเลือกที่ต้องการเนื่องจากสามารถทำทุกอย่างได้onclick และอื่น ๆ อย่าใช้อินไลน์onclickเป็นแอตทริบิวต์ HTML เนื่องจากเป็นการรวม javascript และ HTML เข้าด้วยกันซึ่งเป็นวิธีปฏิบัติที่ไม่ดี มันทำให้รหัสบำรุงรักษาน้อย


และการกำหนดเป้าหมายองค์ประกอบของคุณส่วนใหญ่ทำอย่างไร ฉันหมายความว่าฉันจะไม่ใช้มือแบบอินไลน์onclickเพราะกลัวว่าจะถูกหัวเราะออกไปจากห้อง - แต่โดยปกติแล้วเหตุการณ์ต่าง ๆ จะเลวร้ายลงและมีวิธีดูแลน้อยลงในช่วงไม่กี่ปีที่ผ่านมา เรียนชอบjs-link, js-form-validationหรือข้อมูลคุณลักษณะที่มีdata-jspackage="init"อยู่ในทางใด ๆ ดีกว่า ... และวิธีการ ofteen คุณจริงใช้เดือดเหตุการณ์? โดยส่วนตัวฉันชอบที่จะเขียน handler โดยไม่ตรวจสอบว่าเป้าหมายนั้นตรงกับองค์ประกอบของฉันหรือไม่ต้องหยุดการแพร่กระจายในหลาย ๆ ที่เนื่องจากข้อผิดพลาดแบบสุ่ม
Christoffer Bubach

3

ยังไม่มีการบันทึกรายละเอียดหนึ่ง: เบราว์เซอร์เดสก์ท็อปที่ทันสมัยพิจารณากดปุ่มที่แตกต่างกันเพื่อ "คลิก" สำหรับAddEventListener('click'และonclickโดยค่าเริ่มต้น

  • บน Chrome 42 และ IE11 ทั้งonclickและAddEventListenerคลิกไฟบนคลิกซ้ายและกลาง
  • บน Firefox 38 จะทำการonclickยิงเฉพาะการคลิกซ้าย แต่การAddEventListenerคลิกจะเป็นการคลิกที่ซ้ายกลางและขวา

นอกจากนี้พฤติกรรมการคลิกกลางยังไม่สอดคล้องกันมากในเบราว์เซอร์เมื่อเคอร์เซอร์เลื่อนมีส่วนร่วม:

  • ใน Firefox เหตุการณ์การคลิกกลางจะเริ่มทำงานเสมอ
  • ใน Chrome พวกเขาจะไม่เริ่มทำงานหากปุ่มกลางเปิดหรือปิดเคอร์เซอร์เลื่อน
  • ใน IE พวกมันจะทำงานเมื่อเคอร์เซอร์เลื่อนปิด แต่จะไม่ทำงานเมื่อเปิดขึ้นมา

นอกจากนี้ยังเป็นที่น่าสังเกตว่าเหตุการณ์ "คลิก" สำหรับองค์ประกอบ HTML ใด ๆ ที่สามารถเลือกได้บนแป้นพิมพ์เช่นinputไฟบนพื้นที่หรือป้อนเมื่อองค์ประกอบถูกเลือก


2

Javascript มีแนวโน้มที่จะผสมผสานทุกอย่างเข้ากับวัตถุและอาจทำให้สับสน ทั้งหมดเป็นหนึ่งเป็นวิธี JavaScript

ที่สำคัญ onclick เป็นคุณลักษณะ HTML addEventListener ในทางกลับกันเป็นวิธีการในวัตถุ DOM ที่แสดงองค์ประกอบ HTML

ในวัตถุ JavaScript วิธีการเป็นเพียงคุณสมบัติที่มีฟังก์ชั่นเป็นค่าและทำงานได้กับวัตถุที่แนบมากับ (ใช้ตัวอย่างนี้)

ใน JavaScript เป็นองค์ประกอบ HTML ที่แสดงโดย DOM จะมีการแมปแอตทริบิวต์ของคุณสมบัติของมัน

นี่คือที่ที่ผู้คนสับสนเพราะ JavaScript รวมทุกอย่างไว้ในคอนเทนเนอร์เดียวหรือเนมสเปซโดยไม่มีเลเยอร์ทางอ้อม

ในเลย์เอาต์ OO ปกติ (อย่างน้อยจะรวมเนมสเปซของคุณสมบัติ / วิธีการ) คุณอาจมีลักษณะดังนี้:

domElement.addEventListener // Object(Method)
domElement.attributes.onload // Object(Property(Object(Property(String))))

มีรูปแบบต่าง ๆ เช่นสามารถใช้ getter / setter สำหรับ onload หรือ HashMap สำหรับแอตทริบิวต์ แต่ท้ายที่สุดแล้วมันจะเป็นอย่างไร JavaScript กำจัดเลเยอร์ของการอ้อมโดยคาดหวังว่าจะได้รู้ว่าอะไรคือสิ่งเหนือสิ่งอื่นใด มันรวม domElement และคุณลักษณะเข้าด้วยกัน

การจำกัดความเข้ากันได้ของคุณควรเป็นวิธีปฏิบัติที่ดีที่สุดใช้ addEventListener ในขณะที่คำตอบอื่น ๆ พูดถึงความแตกต่างในเรื่องนั้นมากกว่าความแตกต่างทางโปรแกรมพื้นฐานฉันจะทิ้งมันไป โดยพื้นฐานแล้วในโลกอุดมคติคุณควรใช้กับ * จาก HTML เท่านั้น แต่ในโลกอุดมคติยิ่งกว่านั้นคุณไม่ควรทำสิ่งนั้นจาก HTML

ทำไมวันนี้ถึงเด่น การเขียนเรียนรู้ได้ง่ายกว่าและมีแนวโน้มที่จะทำงานได้เร็วขึ้น

จุดรวมของ onload ใน HTML คือการให้การเข้าถึงเมธอดหรือฟังก์ชั่น addEventListener ตั้งแต่แรก โดยใช้ใน JS คุณจะผ่าน HTML เมื่อคุณสามารถนำไปใช้โดยตรง

สมมุติฐานคุณสามารถสร้างคุณสมบัติของคุณเอง:

$('[myclick]').each(function(i, v) {
     v.addEventListener('click', function() {
         eval(v.myclick); // eval($(v).attr('myclick'));
     });
});

สิ่งที่ JS ทำด้วยนั้นแตกต่างจากนี้เล็กน้อย

คุณสามารถแบ่งให้เท่ากัน (สำหรับทุกองค์ประกอบที่สร้าง):

element.addEventListener('click', function() {
    switch(typeof element.onclick) {
          case 'string':eval(element.onclick);break;
          case 'function':element.onclick();break;
     }
});

รายละเอียดการใช้งานจริงอาจแตกต่างกันไปตามช่วงของการเปลี่ยนแปลงเล็กน้อยทำให้ทั้งสองแตกต่างกันเล็กน้อยในบางกรณี แต่นั่นเป็นส่วนสำคัญของมัน

มันเป็นเนื้อหาที่เข้ากันได้กับแฮ็คที่คุณสามารถปักหมุดฟังก์ชั่นให้กับแอตทริบิวต์เนื่องจากโดยค่าเริ่มต้นคือสตริงทั้งหมด


2

ตามMDNความแตกต่างดังต่อไปนี้:

addEventListener:

กระบวนการ EventTarget.addEventListener () วิธีการเพิ่มวัตถุที่เข้ากันได้ EventListener ระบุในรายการของฟังเหตุการณ์สำหรับประเภทเหตุการณ์ที่ระบุใน EventTarget ที่มันเรียกว่า เป้าหมายเหตุการณ์อาจเป็นองค์ประกอบในเอกสารเอกสารตัวเองหน้าต่างหรือวัตถุอื่น ๆ ที่สนับสนุนกิจกรรม (เช่น XMLHttpRequest)

เมื่อคลิก:

คุณสมบัติ onclick ส่งคืนรหัสตัวจัดการเหตุการณ์การคลิกในองค์ประกอบปัจจุบัน เมื่อใช้เหตุการณ์คลิกเพื่อกระตุ้นการดำเนินการให้พิจารณาเพิ่มการกระทำเดียวกันนี้ในเหตุการณ์การเลื่อนลงเพื่ออนุญาตให้ใช้การกระทำเดียวกันนั้นโดยผู้ที่ไม่ใช้เมาส์หรือหน้าจอสัมผัส องค์ประกอบไวยากรณ์ .click = functionRef; โดยที่ functionRef เป็นฟังก์ชั่น - มักจะเป็นชื่อของฟังก์ชั่นที่ประกาศไว้ที่อื่นหรือการแสดงออกของฟังก์ชั่น ดู "คู่มือ JavaScript: ฟังก์ชั่น" สำหรับรายละเอียด

นอกจากนี้ยังมีความแตกต่างของไวยากรณ์ในการใช้งานตามที่คุณเห็นในรหัสด้านล่าง:

addEventListener:

// Function to change the content of t2
function modifyText() {
  var t2 = document.getElementById("t2");
  if (t2.firstChild.nodeValue == "three") {
    t2.firstChild.nodeValue = "two";
  } else {
    t2.firstChild.nodeValue = "three";
  }
}

// add event listener to table
var el = document.getElementById("outside");
el.addEventListener("click", modifyText, false);

เมื่อคลิก:

function initElement() {
    var p = document.getElementById("foo");
    // NOTE: showAlert(); or showAlert(param); will NOT work here.
    // Must be a reference to a function name, not a function call.
    p.onclick = showAlert;
};

function showAlert(event) {
    alert("onclick Event detected!");
}

1

หากคุณไม่กังวลเกี่ยวกับการสนับสนุนเบราว์เซอร์มีวิธีการอ้างอิงการอ้างอิง 'this' ในฟังก์ชันที่เรียกใช้โดยเหตุการณ์ โดยปกติแล้วมันจะชี้ไปที่องค์ประกอบที่สร้างเหตุการณ์เมื่อมีการใช้งานฟังก์ชันซึ่งไม่ได้เป็นอย่างที่คุณต้องการ ส่วนที่ยุ่งยากก็คือในเวลาเดียวกันสามารถที่จะลบ listener เหตุการณ์เดียวกันได้มากดังที่แสดงในตัวอย่างนี้: http://jsfiddle.net/roenbaeck/vBYu3/

/*
    Testing that the function returned from bind is rereferenceable, 
    such that it can be added and removed as an event listener.
*/
function MyImportantCalloutToYou(message, otherMessage) {
    // the following is necessary as calling bind again does 
    // not return the same function, so instead we replace the 
    // original function with the one bound to this instance
    this.swap = this.swap.bind(this); 
    this.element = document.createElement('div');
    this.element.addEventListener('click', this.swap, false);
    document.body.appendChild(this.element);
}
MyImportantCalloutToYou.prototype = {
    element: null,
    swap: function() {
        // now this function can be properly removed 
        this.element.removeEventListener('click', this.swap, false);           
    }
}

รหัสข้างต้นทำงานได้ดีใน Chrome และอาจมีบางอย่างที่ทำให้การ "ผูก" เข้ากันได้กับเบราว์เซอร์อื่น


1

การใช้ตัวจัดการอินไลน์เข้ากันไม่ได้กับนโยบายความปลอดภัยของเนื้อหาดังนั้นaddEventListenerวิธีการจึงปลอดภัยกว่าจากมุมมองนั้น แน่นอนว่าคุณสามารถเปิดใช้งานตัวจัดการแบบอินไลน์ด้วยunsafe-inlineแต่ตามชื่อที่แนะนำมันไม่ปลอดภัยเนื่องจากจะทำให้จาวาสคริปทั้งหมดของจาวาสคริปต์โจมตีที่ CSP ป้องกัน


1
หมายเหตุ: ข้อ จำกัด ด้านความปลอดภัยนี้ใช้กับการพัฒนาส่วนขยายเท่านั้นและเหตุผลด้านความปลอดภัยที่เสนอในเอกสารที่เชื่อมโยงนั้นส่วนใหญ่จะใช้กับการพัฒนาส่วนขยายของเบราว์เซอร์เท่านั้น จุดหนึ่งที่ทำในเอกสารที่เชื่อมโยงซึ่งเป็นจริงสำหรับการพัฒนาเว็บโดยทั่วไปแม้ว่าจะแยกเนื้อหาจากพฤติกรรม นั่นเป็นวิธีปฏิบัติที่ดีทั่วกระดาน
Chris Baker

1

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

ชอบ

    elm.onclick = myFunctionList
    function myFunctionList(){
      myFunc1();
      myFunc2();
    }

นี่หมายความว่าเราไม่ต้อง chenge การโทรแบบ onclick เพียงแค่เปลี่ยนฟังก์ชั่น myFunctionList () เพื่อทำสิ่งที่เราต้องการ แต่สิ่งนี้ทำให้เราไม่ต้องควบคุมเฟส / การจับฟองดังนั้นควรหลีกเลี่ยงเบราว์เซอร์ใหม่

ในกรณีที่มีคนค้นหากระทู้นี้ในอนาคต ...


1

element.onclick = function () {/ * do stuff * /}

element.addEventListener ('คลิก', ฟังก์ชัน () {/ * ทำสิ่ง * /}, เท็จ);

เห็นได้ชัดว่าพวกเขาทำสิ่งเดียวกัน: ฟังเหตุการณ์คลิกและเรียกใช้ฟังก์ชันการเรียกกลับ อย่างไรก็ตามมันไม่เทียบเท่ากัน หากคุณต้องการเลือกระหว่างสองสิ่งนี้จะช่วยให้คุณทราบว่าอันไหนดีที่สุดสำหรับคุณ

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

ลองมัน: https://jsfiddle.net/fjets5z4/5/

ในตอนแรกฉันถูกล่อลวงให้ใช้ onclick ต่อไปเพราะมันสั้นกว่าและดูง่ายกว่า ... และในความเป็นจริง แต่ฉันไม่แนะนำให้ใช้อีกต่อไป มันเหมือนกับการใช้ JavaScript แบบอินไลน์ การใช้บางอย่างเช่น - นั่นคือ inline JavaScript - หมดกำลังใจอย่างมากในปัจจุบัน (CSS แบบอินไลน์ก็ไม่ได้รับการสนับสนุนเช่นกัน แต่เป็นหัวข้ออื่น)

อย่างไรก็ตามฟังก์ชั่น addEventListener () แม้จะเป็นมาตรฐาน แต่ก็ไม่สามารถใช้งานได้ในเบราว์เซอร์รุ่นเก่า (Internet Explorer ต่ำกว่ารุ่น 9) และนี่เป็นข้อแตกต่างที่สำคัญอีกประการหนึ่ง หากคุณต้องการสนับสนุนเบราว์เซอร์โบราณเหล่านี้คุณควรทำตามวิธีที่คลิก แต่คุณสามารถใช้ jQuery (หรือหนึ่งในทางเลือก): ช่วยให้งานของคุณง่ายขึ้นและลดความแตกต่างระหว่างเบราว์เซอร์ดังนั้นจึงช่วยให้คุณประหยัดเวลาได้มาก

var clickEvent = document.getElementByID("onclick-eg");
var EventListener = document.getElementByID("addEventListener-eg");

clickEvent.onclick = function(){
    window.alert("1 is not called")
}
clickEvent.onclick = function(){
    window.alert("2 is not called")
}

EventListener.addEventListener("click",function(){
    window.alert("1 is called")
})
EventListener.addEventListener("click",function(){
    window.alert("2 is also called")
})

0

addEventListener ให้คุณตั้งค่าตัวจัดการหลายตัว แต่ไม่รองรับใน IE8 หรือต่ำกว่า

IE มีattachEventแต่ก็ไม่เหมือนกันทุกประการ


0

บริบทที่อ้างอิงโดย'this'คำสำคัญใน JavasSript นั้นแตกต่างกัน

ดูรหัสต่อไปนี้:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>

</head>
<body>
    <input id="btnSubmit" type="button" value="Submit" />
    <script>
        function disable() {
            this.disabled = true;
        }
        var btnSubmit = document.getElementById('btnSubmit');
        btnSubmit.onclick = disable();
        //btnSubmit.addEventListener('click', disable, false);
    </script>
</body>
</html>

มันง่ายอะไรจริงๆ เมื่อคุณคลิกปุ่มปุ่มจะถูกปิดใช้งานโดยอัตโนมัติ

ครั้งแรกเมื่อคุณพยายามเชื่อมต่อเหตุการณ์ด้วยวิธีนี้button.onclick = function(), เหตุการณ์ onclick จะถูกเรียกใช้โดยการคลิกปุ่มอย่างไรก็ตามปุ่มจะไม่ถูกปิดใช้งานเนื่องจากไม่มีการเชื่อมโยงอย่างชัดเจนระหว่าง button.onclick และ onclick ตัวจัดการเหตุการณ์ หากคุณดีบักเห็น'this'วัตถุคุณสามารถเห็นมันอ้างถึง'window'วัตถุ

ประการที่สองหากคุณแสดงความคิดเห็นbtnSubmit.onclick = disable();และไม่ แสดงความคิดเห็น//btnSubmit.addEventListener('click', disable, false);คุณจะเห็นว่าปุ่มถูกปิดใช้งานเพราะด้วยวิธีนี้จะมีการเชื่อมโยงอย่างชัดเจนระหว่างเหตุการณ์ button.onclick และตัวจัดการเหตุการณ์ onclick หากคุณแก้ปัญหาในฟังก์ชั่นปิดการใช้งานคุณสามารถดู'this'อ้างอิงถึงbutton controlมากกว่าwindowมากกว่า

นี่คือสิ่งที่ฉันไม่ชอบเกี่ยวกับ JavaScript ซึ่งไม่สอดคล้องกัน Btw หากคุณใช้ jQuery ( $('#btnSubmit').on('click', disable);) จะใช้การรวมที่ชัดเจน


8
คุณต้องเขียนbtnSubmit.onclick = disable;(กำหนดฟังก์ชั่นไม่ใช่เรียกมัน) จากนั้นในทั้งสองกรณีthisจะอ้างถึงองค์ประกอบปุ่ม
มหาอำมาตย์

-1

onclick นั้นเป็น addEventListener ที่ทำหน้าที่เป็นพิเศษเมื่อองค์ประกอบถูกคลิก ดังนั้นมีประโยชน์เมื่อคุณมีปุ่มที่ใช้งานง่ายเช่นปุ่มเครื่องคิดเลข addEventlistener สามารถใช้สำหรับสิ่งต่างๆมากมายเช่นการดำเนินการเมื่อ DOM หรือเนื้อหาทั้งหมดถูกโหลดคล้ายกับ window.onload แต่มีการควบคุมมากขึ้น

หมายเหตุคุณสามารถใช้มากกว่าหนึ่งเหตุการณ์กับอินไลน์หรืออย่างน้อยโดยใช้ onclick โดยแยกแต่ละฟังก์ชันด้วยเซมิโคลอนเช่นนี้ ....

ฉันจะไม่เขียนฟังก์ชันแบบอินไลน์เนื่องจากคุณอาจมีปัญหาในภายหลังและมันจะยุ่งเหยิง imo เพียงใช้เพื่อเรียกฟังก์ชั่นที่ทำไว้แล้วในไฟล์สคริปต์ของคุณ

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

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