Facebook等网站在有未保存的数据时实现离开当前页面的确认。这并不难做到,但我确实需要一些实验来找出有效的方法。我在这篇文章中讨论我的发现。
我正在使用Jinja 模板引擎来生成 HTML 页面。对于客户端,我正在使用JQuery。我提到使用Jinja 模板引擎是为了动摇完整性,无论用于生成动态 HTML 的方法是什么都无关紧要,因为我们正在讨论的纯粹是客户端的。
要实现此离开页面确认,我们需要处理Window: beforeunload 事件。我想为整个网站的所有页面执行此操作,因此我在基本模板中实现它:
File base_template.html
<!doctype html> <html lang="en" class="h-100"> <head> ... <script src="http://localhost/work/jquery/js/jquery-3.6.0.min.js"></script> ... <script> // Individual pages must set and reset this during their operations. let dataChanged = false; const setDataChanged = () => dataChanged = true; const resetDataChanged = () => dataChanged = false; $( document ).ready( function(event) { $( window ).on( 'beforeunload', function( event ) { if ( dataChanged ) // return confirm( 'There are unsaved data. Please confirm.' ); // return false; // return true; return null; }); }); </script> </head> <body class="d-flex flex-column h-100"> {% block content %} <!-- Content of specific individual pages go here. --> {% endblock %} </body> </html>
唯一的事情“金贾”关于这个页面是以下块:
{% block content %} <!-- Content of specific individual pages go here. --> {% endblock %}
基本上,在运行时,处理引擎将此块替换为请求的页面,以制作完整且有效的HTML页面以返回到请求客户端。
beforeunload事件的代码很简单:如果变量dataChanged为true,则返回null,否则什么都不做。
我注释掉了三 (3) 个返回语句:它们与返回 null 具有相同的效果。
页面负责分别通过调用setDataChanged()和resetDataChanged()来设置和重置dataChanged。请注意,当页面首次加载时,dataChanged被初始化为false。
进入base_template.html块内容的单个页面的一般结构:
File a_specific_page.html
{% extends "page_template.html" %} {% block content %} <script> function bindDataChange() { $( '.selector-input, input[type="checkbox"]' ).on( 'change', function(event) { ... setDataChanged(); event.preventDefault(); }); }; function bindSave() { function savedSuccessful( data ) { resetDataChanged(); ... }; $( '#saveBtn' ).on( 'click', function( even ) { if ( !$('#somethingFrm').parsley().validate() ) return false; // Send data to server using AJAX. Response is JSON status. saveData( '/save-something/', '{{ csrf_token() }}', $( '#somethingFrm' ).serialize(), savedSuccessful ); event.preventDefault(); }); }; $( document ).ready( function() { ... bindDataChange(); bindSave(); ... }); </script> <div class="d-flex row justify-content-center h-100"> ... </div> {% endblock %}
注意setDataChanged() 和 resetDataChanged() 被调用的位置。还请记住,当页面首次加载时,dataChanged被初始化为false。
此a_specific_page.html通过AJAX调用保存数据,响应是JSON状态,指示请求的结果:在此操作期间不会重新加载页面。
简而言之,每当用户在屏幕上执行任何需要持久化数据的操作时,都必须调用setDataChanged()。成功保存数据后,必须调用重置数据更改()。