Sự kiện thoát trang chặn


117

Khi chỉnh sửa một trang trong hệ thống của tôi, người dùng có thể quyết định điều hướng đến một trang web khác và làm như vậy có thể mất tất cả các chỉnh sửa mà họ chưa lưu.

Tôi muốn ngăn chặn mọi nỗ lực truy cập trang khác và nhắc người dùng chắc chắn rằng họ muốn điều này xảy ra vì họ có thể bị mất công việc hiện tại.

Gmail thực hiện điều này theo cách tương tự. Ví dụ: soạn một email mới, bắt đầu nhập vào nội dung thư và nhập một vị trí mới vào thanh địa chỉ (giả sử twitter.com hoặc một cái gì đó). Nó sẽ nhắc bạn hỏi "Bạn có chắc không?"

Ý tưởng làm thế nào để nhân rộng điều này? Tôi đang nhắm mục tiêu IE8, nhưng cũng muốn tương thích với FF & Chrome.


Câu trả lời:


154

Tương tự như câu trả lời của Ghommey, nhưng điều này cũng hỗ trợ các phiên bản cũ của IE và Firefox.

window.onbeforeunload = function (e) {
  var message = "Your confirmation message goes here.",
  e = e || window.event;
  // For IE and Firefox
  if (e) {
    e.returnValue = message;
  }

  // For Safari
  return message;
};

1
Bạn có thể giải thích dòng đầu tiên (var message = ...)? Tôi không biết dấu phẩy đó và biểu thức thứ hai đang làm gì.
mtmurdock 27/07/12

7
@mtmurdock Đó chỉ là cú pháp Javascript để khai báo nhiều biến. var foo, bar;giống nhưvar foo; var bar;
T Nguyen

4
@mtmurdock, Câu lệnh thứ hai " var e = e || window.event;" có nghĩa là đặt e bằng tham số e (nếu nó đúng) hoặc window.event nếu không đúng. Nó sẽ không đúng nếu tham số e là null.
T Nguyen

3
@Blieque addEventListener không được hỗ trợ trong IE8. Đừng chỉnh sửa câu trả lời của mọi người mà không cần đọc câu hỏi.
Eli Grey

2
Không hoạt động nữa trong Chrome (phản đối): developers.google.com/web/updates/2016/04/...
Micha Schwab

25

Xem bài viết này. Tính năng bạn đang tìm kiếm là onbeforeunload

mã mẫu:

  <script language="JavaScript">
  window.onbeforeunload = confirmExit;
  function confirmExit()
  {
    return "You have attempted to leave this page.  If you have made any changes to the fields without clicking the Save button, your changes will be lost.  Are you sure you want to exit this page?";
  }
</script>

2
Có cách nào để xác định rằng người dùng đã chọn tùy chọn "Rời khỏi trang này" thay vì "Ở lại trang này" không?
Shilpa Soni

@ShilpaSoni, bạn sẽ sớm nhận được sự kiện dỡ bỏ tiếp theo, developer.mozilla.org/en-US/docs/Web/API/Window/unload_event nhưng tôi không nghĩ rằng có một cách đồng bộ.
scipilot

6

Thay vì một cửa sổ bật lên xác nhận gây phiền nhiễu, sẽ rất tuyệt nếu bạn chỉ cần hoãn lại một chút (vấn đề mili giây) để quản lý việc đăng thành công dữ liệu chưa lưu lên máy chủ mà tôi đã quản lý cho trang web của mình bằng cách viết văn bản giả vào bảng điều khiển như sau:

window.onbeforeunload=function(e){
  // only take action (iterate) if my SCHEDULED_REQUEST object contains data        
  for (var key in SCHEDULED_REQUEST){   
    postRequest(SCHEDULED_REQUEST); // post and empty SCHEDULED_REQUEST object
    for (var i=0;i<1000;i++){
      // do something unnoticable but time consuming like writing a lot to console
      console.log('buying some time to finish saving data'); 
    };
    break;
  };
}; // no return string --> user will leave as normal but data is send to server

Chỉnh sửa: Xem thêm Synchronous_AJAX và cách thực hiện điều đó với jquery


Tôi thích sự thay thế này cho cửa sổ bật lên. Cảm ơn lời đề nghị, Remi.
Chris Ballance,

2
điều đó không hoàn toàn vô nghĩa -1. javascript không phải là chuỗi những gì bạn đang làm là thực hiện một postRequest và sau đó tạm dừng tính toán của trang web mà không cho phép không ai làm gì cả (kể cả postRequest của bạn, trong khi đó đã được gửi trước khi tạm dừng tính toán).
fmsf

Và đó chính xác là lý do tại sao nó hoạt động: thực sự yêu cầu đăng được gửi trước khi tạm dừng tính toán, nhưng việc chặn trang nhỏ này trước khi nó thực sự được để lại đảm bảo đủ thời gian để ứng dụng khách trình duyệt (không phải javascript) thực sự hoàn thành việc gửi yêu cầu này đúng cách . Tôi nhận thấy rằng khi tôi chỉ gửi yêu cầu (không chặn) và rời khỏi trang ngay sau đó, yêu cầu không phải lúc nào cũng được gửi.
Remi

6
Tôi sẽ không sử dụng nó trong sản xuất. console.log không phải là trình duyệt chéo; mỗi postRequest đều gặp phải sự chậm trễ của những post trước (điều đó cũng có nghĩa là trang sẽ bị treo ở đó trong khoảng thời gian của vòng lặp * các yêu cầu đã lên lịch của bạn); các yêu cầu không được bắt đầu song song; bạn không được đảm bảo thực sự gửi yêu cầu của mình. Nếu tôi buộc phải đối mặt với vấn đề này, tôi sẽ thực hiện một yêu cầu ajax đồng bộ, nếu chỉ có một yêu cầu. Với nhiều yêu cầu, tôi sẽ sử dụng các yêu cầu ajax không đồng bộ và một vòng lặp kiểm tra kết quả (thành công hoặc lỗi) từ các lệnh gọi lại của các yêu cầu.
framp

Tôi không biết rằng console.log không phải là trình duyệt chéo và yêu cầu Ajax đồng bộ thực sự phải là giải pháp ưu tiên (cho một yêu cầu duy nhất). Đối tượng được đề cập SCHEDULED_REQUESTlà một đối tượng tích lũy bất kỳ thông tin không khẩn cấp nào cần được gửi đến máy chủ, giống như bộ đệm dữ liệu, kết hợp hiệu quả nhiều yêu cầu với một (tất nhiên url của các yêu cầu này là giống nhau). Sử dụng yêu cầu Ajax đồng bộ trước khi tải xuống sẽ giải quyết được vấn đề trình duyệt chéo như bạn đã nói. Cảm ơn cho bình luận có giá trị của bạn!
Remi

0

Tôi có những người dùng chưa hoàn thành tất cả dữ liệu bắt buộc.

<cfset unloadCheck=0>//a ColdFusion precheck in my page generation to see if unload check is needed
var erMsg="";
$(document).ready(function(){
<cfif q.myData eq "">
    <cfset unloadCheck=1>
    $("#myInput").change(function(){
        verify(); //function elsewhere that checks all fields and populates erMsg with error messages for any fail(s)
        if(erMsg=="") window.onbeforeunload = null; //all OK so let them pass
        else window.onbeforeunload = confirmExit(); //borrowed from Jantimon above;
    });
});
<cfif unloadCheck><!--- if any are outstanding, set the error message and the unload alert --->
    verify();
    window.onbeforeunload = confirmExit;
    function confirmExit() {return "Data is incomplete for this Case:"+erMsg;}
</cfif>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.