ป้องกันการรีเฟรชหน้าทุกรูปแบบโดยใช้ jQuery / Javascript


93

เมื่อผู้ใช้อยู่ในหน้าของฉันฉันไม่ต้องการให้เขารีเฟรชหน้านี้

  1. เมื่อใดก็ตามที่ผู้ใช้F5กดปุ่มหรือรีเฟรชที่ด้านบน เขาควรได้รับการแจ้งเตือนว่า

    คุณไม่สามารถรีเฟรชเพจได้

  2. นอกจากนี้หากผู้ใช้เปิดแท็บใหม่และพยายามเข้าถึง url เดียวกันในแท็บก่อนหน้าเขาควรได้รับการแจ้งเตือน

    คุณไม่สามารถเปิดหน้าเดียวกันใน 2 แท็บ

อย่างไรก็ตามฉันสามารถทำได้โดยใช้ JavaScript หรือ jQuery? จุดที่หนึ่งสำคัญมาก


คุณสามารถตรวจจับได้โดยใช้ Broadcast Channel API ( developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API ) และส่งข้อความเพื่อสื่อสารระหว่างแท็บ THUS โดยใช้สิ่งนี้คุณสามารถตรวจจับหลายแท็บที่มี url เดียวกันและบล็อกแท็บอื่น ๆ
aeXuser264

คำตอบ:


195

# 1 สามารถดำเนินการผ่านwindow.onbeforeunload.

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

<script type="text/javascript">
    window.onbeforeunload = function() {
        return "Dude, are you sure you want to leave? Think of the kittens!";
    }
</script>

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

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

ในความเป็นจริงระบบออนไลน์ของธนาคารของฉันพยายามอย่างมากที่จะทำ # 2 และสถานการณ์ที่อธิบายไว้ข้างต้นเกิดขึ้นตลอดเวลา ฉันมักจะต้องรอจนกว่าเซสชันฝั่งเซิร์ฟเวอร์จะหมดอายุก่อนจึงจะสามารถใช้ระบบธนาคารได้อีกครั้ง


1
โปรดทราบว่าเหตุการณ์ onbeforeunload ไม่สามารถใช้ได้ในเบราว์เซอร์ Opera เวอร์ชันต่างๆ
WillyCornbread

1
มีวิธีดำเนินการบางอย่างหรือไม่หากผู้ใช้เลือกที่จะอยู่บนเพจ
riship89

5
เคล็ดลับสำหรับฉันแม้ว่าคุณควรใช้ window.addEventListener (ดูdeveloper.mozilla.org/en-US/docs/Web/Events/beforeunload ) แทนสำหรับความเข้ากันได้ข้ามเบราว์เซอร์และเพื่อป้องกันปัญหาไลบรารี
Julien Bérubé

ฉันรู้ว่าคำถามนี้เก่า แต่หากพวกเขาต้องการป้องกันหลายเซสชันจริงๆพวกเขาสามารถใช้ WebSockets ได้หรือไม่
Meghan

1
@Sean - Yup ... ถ้าคุณจริงๆต้องการที่จะป้องกันไม่ให้หลายครั้ง WebSocket สามารถทำการสื่อสารแบบสองทิศทางแบบ stateful ไคลเอนต์ (อาจ) จะไม่กลายเป็นคนอื่นในทันทีในขณะที่เชื่อมต่อ WebSocket ดังนั้นคุณควรจะสามารถกำหนดโทเค็นให้กับผู้ใช้รายนั้นและล้างได้เมื่อซ็อกเก็ตปิดลง แต่มันเป็นการแฮ็กพฤติกรรมที่คาดหวังของตัวแทนผู้ใช้ดังนั้นจึงอาจเป็น UX ที่ไม่ดี ฉันนึกถึงบางกรณีที่สิ่งนี้จะเหมาะสม (อาจเป็นเกมออนไลน์ - เพื่อป้องกันไม่ให้ใครบางคนเข้าสู่ระบบด้วยกรงเล็บแห่งความตายระดับ 37 สองตัว ... )
Seth

34

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

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


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

20
@pankaj - สิ่งนี้ควรได้รับการแก้ไขบนไซต์แอปพลิเคชันและคุกกี้เป็นต้นเพื่อให้ผู้ใช้แชร์เซสชันข้ามแท็บ
Nick Craver

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

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

16

แม้ว่าจะไม่ใช่ความคิดที่ดีที่จะปิดใช้งานคีย์ F5 แต่คุณสามารถทำได้ใน JQuery ดังต่อไปนี้

<script type="text/javascript">
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };

$(document).ready(function(){
     $(document).on("keydown", disableF5);
});
</script>

หวังว่านี่จะช่วยได้!


29
แล้ว OSX CMD + R อยู่ที่ไหน หรือมือถือมีปุ่มให้กดตรงไหน? ฉันไม่เห็นว่านี่เป็นวิธีแก้ปัญหา
ItalyPaleAle

14

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

หากผู้ใช้อยู่ในหน้าที่มีข้อความว่า "โปรดรอสักครู่ ... กำลังทำงานใหญ่ซึ่งอาจใช้เวลาสักครู่" พวกเขามีแนวโน้มที่จะกด REFRESH และนี่จะไม่ดี!

ทำไม? เพราะมันจะทำให้เกิดงานที่ช้ามากขึ้นและทำให้ทุกอย่างชะงักในที่สุด

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

โดยที่หน้าที่อยู่ตรงกลางจะเก็บข้อมูลแบบฟอร์มที่จำเป็นในการเริ่มงาน อย่างไรก็ตามหน้า WAIT มีการทำลายประวัติจาวาสคริปต์ ดังนั้นพวกเขาจึงสามารถ RELOAD หน้าที่รอทั้งหมดที่พวกเขาต้องการและจะไม่ทำให้งานเดิมเริ่มทำงานในพื้นหลังเนื่องจากหน้า WAIT นั้นมีเฉพาะข้อมูลฟอร์มที่จำเป็นสำหรับการ WAIT เท่านั้น

หวังว่าจะสมเหตุสมผล

ฟังก์ชันทำลายประวัติยังป้องกันไม่ให้คลิกย้อนกลับแล้วรีเฟรชอีกด้วย

มันราบรื่นมากและทำงานได้ดีมากเป็นเวลาหลายปีจนกระทั่งองค์กรไม่แสวงหาผลกำไรได้รับความเสียหาย

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

การตอบสนองจากการป้อนแบบฟอร์ม - ส่งคืน HTML ที่ดำเนินการเปลี่ยนเส้นทางไปยังเพจรอคงที่ของคุณและ / หรือ POST / GET ไปยังฟอร์มอื่น (เพจ WAIT)

WAIT PAGE - มีเฉพาะข้อมูล FORM ที่เกี่ยวข้องกับหน้าที่รอเช่นเดียวกับจาวาสคริปต์เพื่อทำลายประวัติล่าสุด กดไลค์ (-1 หรือ -2) เพื่อทำลายเฉพาะเพจล่าสุด แต่ยังคงอนุญาตให้กลับไปที่หน้ารายการฟอร์มเดิมได้

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

หากพวกเขาทำการ REFRESH ด้วยตนเอง ... พวกเขาก็เพิ่มการตรวจสอบสถานะงานของพวกเขาอีกหนึ่งครั้งในนั้น

หวังว่าจะช่วยได้ โชคดี.


2
คุณไม่ได้รับเครดิตเพียงพอสำหรับคำตอบที่น่าทึ่งและให้ข้อมูลนี้ ขอบคุณ!!
ShiningLight

5

ไม่มีไม่มี

ฉันค่อนข้างแน่ใจว่าไม่มีวิธีใดที่จะสกัดกั้นการคลิกที่ปุ่มรีเฟรชจาก JS ได้และแม้ว่าจะมีอยู่ก็สามารถปิด JS ได้

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


3

ฉบับที่ 2 ขณะนี้สามารถแก้ไขได้โดยใช้BroadcastAPI

ในขณะนี้ใช้ได้เฉพาะใน Chrome, Firefox และ Opera

var bc = new BroadcastChannel('test_channel');

bc.onmessage = function (ev) { 
    if(ev.data && ev.data.url===window.location.href){
       alert('You cannot open the same page in 2 tabs');
    }
}

bc.postMessage(window.location.href);

2

หมายเลข (2) เป็นไปได้โดยใช้การใช้งานซ็อกเก็ต (เช่น websocket, socket.io ฯลฯ ) พร้อมกับ heartbeat ที่กำหนดเองสำหรับแต่ละเซสชันที่ผู้ใช้มีส่วนร่วมหากผู้ใช้พยายามเปิดหน้าต่างอื่นคุณจะมีการตรวจสอบตัวจัดการ javascript กับเซิร์ฟเวอร์ถ้ามันโอเคแล้วตอบกลับด้วยข้อความแสดงข้อผิดพลาด

อย่างไรก็ตามทางออกที่ดีกว่าคือการซิงโครไนซ์ทั้งสองเซสชันหากเป็นไปได้เช่นใน Google เอกสาร

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