ฉันจะหยุดไม่ให้หน้าเว็บเลื่อนขึ้นไปด้านบนเมื่อมีการคลิกลิงก์ที่เรียกใช้ JavaScript ได้อย่างไร


140

เมื่อฉันมีลิงค์ที่เชื่อมต่อกับเหตุการณ์ jQuery หรือ JavaScript เช่น:

<a href="#">My Link</a>

ฉันจะป้องกันไม่ให้เลื่อนไปด้านบนได้อย่างไร เมื่อฉันลบแอตทริบิวต์ href ออกจากจุดยึดหน้าเว็บจะไม่เลื่อนไปด้านบน แต่ดูเหมือนว่าลิงก์จะไม่สามารถคลิกได้

คำตอบ:


199

คุณต้องป้องกันไม่ให้การดำเนินการเริ่มต้นสำหรับเหตุการณ์คลิก (เช่นการนำทางไปยังเป้าหมายลิงก์) ไม่ให้เกิดขึ้น

มีสองวิธีในการทำเช่นนี้

ตัวเลือกที่ 1: event.preventDefault()

เรียกใช้.preventDefault()เมธอดของวัตถุเหตุการณ์ที่ส่งผ่านไปยังตัวจัดการของคุณ หากคุณใช้ jQuery เพื่อผูกตัวจัดการของคุณเหตุการณ์นั้นจะเป็นอินสแตนซ์ของjQuery.Eventและจะเป็นเวอร์ชัน jQuery ของ.preventDefault(). หากคุณกำลังใช้addEventListenerเพื่อผูกตัวจัดการของคุณจะเป็นEventเวอร์ชัน DOM และดิบของ.preventDefault(). ไม่ว่าจะด้วยวิธีใดก็ตามที่คุณต้องการ

ตัวอย่าง:

$('#ma_link').click(function($e) {
    $e.preventDefault();
    doSomething();
});

document.getElementById('#ma_link').addEventListener('click', function (e) {
    e.preventDefault();
    doSomething();
})

ทางเลือกที่ 2: return false;

ใน jQuery :

การส่งคืนเท็จจากตัวจัดการเหตุการณ์จะเรียก event.stopPropagation () และ event.preventDefault () โดยอัตโนมัติ

ดังนั้นด้วย jQuery คุณสามารถใช้วิธีนี้เพื่อป้องกันพฤติกรรมลิงก์เริ่มต้น:

$('#ma_link').click(function(e) {
     doSomething();
     return false;
});

หากคุณใช้เหตุการณ์ DOM แบบดิบสิ่งนี้จะใช้ได้กับเบราว์เซอร์สมัยใหม่ด้วยเนื่องจากข้อกำหนด HTML 5 กำหนดพฤติกรรมนี้ อย่างไรก็ตามข้อกำหนดรุ่นเก่าไม่ได้ดังนั้นหากคุณต้องการความเข้ากันได้สูงสุดกับเบราว์เซอร์รุ่นเก่าคุณควรโทรติดต่อ.preventDefault()อย่างชัดเจน ดูevent.preventDefault () เทียบกับ return false (ไม่มี jQuery)สำหรับรายละเอียดข้อมูลจำเพาะ


9
โพสต์วิธีแก้ปัญหา (ช้าไป 3 ปี) ที่ไม่ต้องแนบตัวจัดการการคลิก: stackoverflow.com/a/11246131/216941
Matt Crinklaw-Vogt

ในกรณีนี้ Achilles ทำสิ่งนี้เพียงเพราะเขาต้องการให้ลิงก์ปรากฏแบบคลิกได้ซึ่งเขาไม่จำเป็นต้องใช้ href = "#" เลย ดูคำตอบของฉันสำหรับข้อมูลเพิ่มเติม
achecopar

167

คุณสามารถตั้งค่า href ของคุณเป็น#!แทน#

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

<a href="#!">Link</a>

จะไม่ทำการเลื่อนใด ๆ เมื่อคลิก

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

นี่คือ Fiddle ที่แสดงสิ่งนี้ (เพียงแค่ scrunch เบราว์เซอร์ของคุณลงจนกว่าคุณจะได้รับแถบเลื่อน):
http://jsfiddle.net/9dEG7/


สำหรับข้อมูลจำเพาะ - เหตุใดจึงได้ผล:

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

2. ถ้าfragidเป็นสตริงว่างส่วนที่ระบุของเอกสารจะอยู่ด้านบนสุดของเอกสาร

การใช้ href "#!"แทนใช้งานได้เพียงเพราะหลีกเลี่ยงกฎนี้ ไม่มีอะไรวิเศษเกี่ยวกับเครื่องหมายอัศเจรีย์ - เพียงแค่สร้างตัวระบุส่วนที่ใช้งานได้สะดวกเนื่องจากแตกต่างอย่างเห็นได้ชัดกับความเปราะบางทั่วไปและไม่น่าจะตรงกับidหรือnameองค์ประกอบบนหน้าของคุณ อันที่จริงเราสามารถใส่เกือบทุกอย่างหลังการแฮช เศษส่วนเพียงอย่างเดียวที่ไม่เพียงพอคือสตริงว่างคำว่า 'top' หรือสตริงที่ตรงกับnameหรือidแอตทริบิวต์ขององค์ประกอบบนหน้า

ยิ่งไปกว่านั้นเราแค่ต้องการตัวระบุส่วนที่จะทำให้เราผ่านไปยังขั้นตอนที่ 8 ในอัลกอริทึมต่อไปนี้เพื่อกำหนดส่วนที่ระบุของเอกสารจากส่วนย่อย

  1. ใช้อัลกอริธึมตัวแยกวิเคราะห์ URL กับ URL และปล่อยให้Fragidเป็นส่วนประกอบส่วนย่อยของ URL ที่แยกวิเคราะห์ผลลัพธ์

  2. ถ้าfragidเป็นสตริงว่างส่วนที่ระบุของเอกสารจะอยู่ด้านบนสุดของเอกสาร หยุดอัลกอริทึมที่นี่

  3. อนุญาตเป็นผลมาจากร้อยละถอดรหัสfragid bytesfragid

  4. อนุญาตdecoded fragidเป็นผลมาจากการใช้ขั้นตอนวิธีการถอดรหัส UTF-8 fragid bytesไป หากตัวถอดรหัส UTF-8 แสดงข้อผิดพลาดของตัวถอดรหัสให้ยกเลิกตัวถอดรหัสและข้ามไปยังขั้นตอนที่ระบุว่าno decoded fragidแทน

  5. หากมีองค์ประกอบใน DOM ที่มี ID เท่ากับdecoded fragidองค์ประกอบแรกดังกล่าวตามลำดับแบบต้นไม้คือส่วนที่ระบุของเอกสาร หยุดอัลกอริทึมที่นี่

  6. ไม่มีการถอดรหัส Fragid : หากมีองค์ประกอบใน DOM ที่มีแอตทริบิวต์ name ซึ่งมีค่าเท่ากับfragid( notdecoded fragid ) องค์ประกอบแรกดังกล่าวตามลำดับแบบต้นไม้คือส่วนที่ระบุของเอกสาร หยุดอัลกอริทึมที่นี่

  7. หากFragidเป็นการจับคู่ ASCII ที่ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่สำหรับสตริงtopส่วนที่ระบุของเอกสารจะอยู่ด้านบนสุดของเอกสาร หยุดอัลกอริทึมที่นี่

  8. มิฉะนั้นจะไม่มีส่วนที่ระบุของเอกสาร

ตราบใดที่เราเข้าสู่ขั้นตอนที่ 8 และไม่มีส่วนที่ระบุของเอกสารกฎต่อไปนี้จะมีผล:

หากไม่มีส่วนที่ระบุ ... ตัวแทนผู้ใช้จะต้องไม่ทำอะไรเลย

ซึ่งเป็นสาเหตุที่ทำให้เบราว์เซอร์ไม่เลื่อน


4
ไม่สำคัญว่าคุณจะใส่ "!" หรือค่าอื่น ๆ ตราบใดที่ id ไม่ได้เป็นส่วนหนึ่งของ DOM
ปินาถ

3
หลังจากเคยเป็นผู้สนับสนุนวิธีนี้ฉันได้ทำ 180 แล้วและแนะนำให้ต่อต้านมัน ระวัง: ลิงก์เช่นนี้จะยังคงเปลี่ยน URL ของหน้าทำให้มีรายการเพิ่มเติมในประวัติของเบราว์เซอร์และทำให้ปุ่ม "ย้อนกลับ" เพียงแค่ลบส่วนย่อยออกจาก URL แทนที่จะทำตามที่ผู้ใช้คาดหวัง ดังนั้นวิธีการแก้ปัญหานี้ในขณะที่ตอบคำถามตามที่ถามโดยทั่วไปแล้วไม่ใช่ทางเลือกที่พึงปรารถนาในการใช้preventDefault()ในตัวจัดการการคลิก - ค่อนข้างน่าเศร้า
Mark Amery

1
ทำไมไม่ใช้ href = "javascript :;" แทน? เท่าที่ฉันรู้ว่ามันจะไม่เปลี่ยนประวัติของเบราว์เซอร์ โพสต์เกี่ยวกับเรื่องนี้ในคำตอบของฉัน
achecopar

นี่ควรเป็นคำตอบที่ยอมรับได้
Aman

32

แนวทางง่ายๆคือการใช้ประโยชน์จากรหัสนี้:

<a href="javascript:void(0);">Link Title</a>

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

ด้วยเหตุผลเหล่านี้วิธีแก้ปัญหาข้างต้นจึงดีกว่า:

<a href="javascript:myClickHandler();">Link Title</a>
<a href="#" onclick="myClickHandler(); return false;">Link Title</a>

โดยที่วิธีสุดท้ายจะหลีกเลี่ยงปัญหาการเลื่อน - กระโดดหากวิธีการ myClickHandler ไม่ล้มเหลว


12

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

<a href="javascript:;">Link Title</a>

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


10

คุณควรเปลี่ยนไฟล์

<a href="#">My Link</a>

ถึง

<a href="javascript:;">My Link</a>

วิธีนี้เมื่อคลิกลิงก์หน้าจะไม่เลื่อนขึ้นไปด้านบน วิธีนี้สะอาดกว่าการใช้ href = "#" แล้วป้องกันไม่ให้เหตุการณ์เริ่มต้นทำงาน

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



4

หากคุณสามารถเปลี่ยนhrefค่าได้คุณควรใช้:

<a href="javascript:void(0);">Link Title</a>

วิธีแก้ปัญหาที่เป็นระเบียบอีกวิธีหนึ่งที่ฉันเพิ่งสร้างขึ้นคือการใช้ jQuery เพื่อหยุดการคลิกไม่ให้เกิดขึ้นและทำให้หน้าเลื่อน แต่สำหรับhref="#"ลิงก์เท่านั้น

<script type="text/javascript">
    /* Stop page jumping when links are pressed */
    $('a[href="#"]').live("click", function(e) {
         return false; // prevent default click action from happening!
         e.preventDefault(); // same thing as above
    });
</script>

แน่นอนว่าreturn falseควรอยู่หลังpreventDefault()เส้นมิฉะนั้นคุณจะไม่ไปถึงบรรทัดที่สองนี้?
hobailey

3

ลิงก์ไปยังสิ่งที่สมเหตุสมผลมากกว่าด้านบนของหน้าในตอนแรก จากนั้นยกเลิกเหตุการณ์เริ่มต้น

ดูกฎข้อที่ 2 ของการเพิ่มประสิทธิภาพของความก้าวหน้าการปฏิบัติ


นอกจากนี้ยังทำให้เว็บไซต์ของคุณเป็นมิตรกับ SEO มากขึ้น
Frankie

3

นอกจากนี้คุณสามารถใช้event.preventDefaultภายในแอตทริบิวต์onclick

<a href="#" onclick="event.preventDefault(); doSmth();">doSmth</a>

ไม่จำเป็นต้องเขียนเหตุการณ์คลิก exstra




0

สร้างเพจที่มีสองลิงค์ - อันหนึ่งที่ด้านบนและอีกอันที่ด้านล่าง เมื่อคลิกลิงก์บนสุดหน้าจะต้องเลื่อนลงไปที่ด้านล่างของหน้าที่มีลิงค์ด้านล่าง เมื่อคลิกลิงก์ด้านล่างหน้าจะต้องเลื่อนขึ้นไปที่ด้านบนของหน้า



0

คุณอาจต้องการตรวจสอบ CSS ของคุณ ในตัวอย่างที่นี่: https://css-tricks.com/the-checkbox-hack/position: absolute; top: -9999px;มี สิ่งนี้เป็นเรื่องตลกโดยเฉพาะบน Chrome เนื่องจากonclick="whatever"ยังคงข้ามไปยังตำแหน่งที่แน่นอนขององค์ประกอบที่คลิก

ถอดposition: absolute; top: -9999px;สำหรับdisplay: none;อาจช่วย


0

สำหรับ Bootstrap 3 สำหรับการยุบหากคุณไม่ระบุ data-target บนจุดยึดและพึ่งพา href เพื่อกำหนดเป้าหมายเหตุการณ์จะถูกป้องกัน หากคุณใช้ data-target คุณจะต้องป้องกันเหตุการณ์ด้วยตัวเอง

<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#demo">Collapse This</button>

<div id="demo" class="collapse"> 
<p>Lorem ipsum dolor sit amet</p>
</div>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.