วิธีที่ดีที่สุดในการตรวจสอบว่าผู้ใช้ออกจากหน้าเว็บคืออะไร?
onunloadเหตุการณ์ JavaScript ไม่ทำงานทุกครั้ง (การร้องขอ HTTP ใช้เวลานานกว่าเวลาที่จะต้องยุติการเบราว์เซอร์)
การสร้างอาจจะถูกบล็อกโดยเบราว์เซอร์ปัจจุบัน
วิธีที่ดีที่สุดในการตรวจสอบว่าผู้ใช้ออกจากหน้าเว็บคืออะไร?
onunloadเหตุการณ์ JavaScript ไม่ทำงานทุกครั้ง (การร้องขอ HTTP ใช้เวลานานกว่าเวลาที่จะต้องยุติการเบราว์เซอร์)
การสร้างอาจจะถูกบล็อกโดยเบราว์เซอร์ปัจจุบัน
คำตอบ:
ลองonbeforeunloadเหตุการณ์: มันถูกไล่ออกก่อนที่หน้าจะถูกยกเลิกการโหลด นอกจากนี้ยังอนุญาตให้คุณถามกลับว่าผู้ใช้ต้องการออกจริงหรือไม่ ดูการสาธิตonbeforeunload สาธิต
หรือคุณสามารถส่งคำขอAjaxเมื่อเขาออกไป
Mozilla พัฒนาเครือข่ายมีคำอธิบายที่ดีและตัวอย่างของonbeforeunload
หากคุณต้องการเตือนผู้ใช้ก่อนออกจากหน้าหากหน้าเว็บของคุณสกปรก (เช่นหากผู้ใช้ป้อนข้อมูลบางส่วน):
window.addEventListener('beforeunload', function(e) {
var myPageIsDirty = ...; //you implement this logic...
if(myPageIsDirty) {
//following two lines will cause the browser to ask the user if they
//want to leave. The text of this dialog is controlled by the browser.
e.preventDefault(); //per the standard
e.returnValue = ''; //required for Chrome
}
//else: user is allowed to leave without a warning dialog
});
ต่อไปนี้เป็นทางเลือกอื่นเนื่องจากในเบราว์เซอร์ส่วนใหญ่การควบคุมการนำทาง (แถบนำทางแท็บ ฯลฯ ) ตั้งอยู่เหนือพื้นที่เนื้อหาของหน้าคุณสามารถตรวจสอบตัวชี้เมาส์ออกจากหน้าผ่านทางด้านบนและแสดง " ก่อนออกจาก " โต้ตอบ มันไม่สร้างความรำคาญอย่างสมบูรณ์และช่วยให้คุณสามารถโต้ตอบกับผู้ใช้ก่อนที่พวกเขาจะออกจากการกระทำจริง
$(document).bind("mouseleave", function(e) {
if (e.pageY - $(window).scrollTop() <= 1) {
$('#BeforeYouLeaveDiv').show();
}
});
ข้อเสียคือแน่นอนว่ามันเป็นเดาว่าผู้ใช้จริงมีความตั้งใจที่จะออก แต่ในส่วนใหญ่ของกรณีมันถูกต้อง
สำหรับสิ่งนี้ฉันใช้:
window.onbeforeunload = function (e) {
}
มันถูกไล่ออกก่อนที่จะยกเลิกการโหลดหน้าเว็บ
onbeforeunloadอย่างไร
ฉันรู้ว่าคำถามนี้ได้รับการตอบแล้ว แต่ในกรณีที่คุณต้องการให้สิ่งที่จะเรียกเมื่อเบราว์เซอร์ที่แท้จริงถูกปิดและไม่เพียงเมื่อ pageload เกิดขึ้นคุณสามารถใช้รหัสนี้:
window.onbeforeunload = function (e) {
if ((window.event.clientY < 0)) {
//window.localStorage.clear();
//alert("Y coords: " + window.event.clientY)
}
};
ในตัวอย่างของฉันฉันกำลังเคลียร์ที่เก็บข้อมูลโลคัลและแจ้งเตือนผู้ใช้ด้วย mouses y coords เฉพาะเมื่อปิดเบราว์เซอร์เท่านั้นสิ่งนี้จะถูกละเว้นในทุกหน้าโหลดจากภายในโปรแกรม
eควรใช้พารามิเตอร์เหตุการณ์ ( ตัวแปรในกรณีนี้): stackoverflow.com/questions/9813445/ …
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. developer.mozilla.org/en-US/docs/Web/API/Window/event
วิธีหนึ่ง (แฮ็คเล็กน้อย) เพื่อแทนที่และลิงก์ที่นำไปจากไซต์ของคุณด้วยการโทร AJAX ไปยังฝั่งเซิร์ฟเวอร์เพื่อระบุว่าผู้ใช้กำลังออกจากนั้นใช้บล็อกจาวาสคริปต์เดียวกันเพื่อนำผู้ใช้ไปยังไซต์ภายนอกที่พวกเขา ได้รับการร้องขอ
แน่นอนว่าสิ่งนี้จะไม่ทำงานหากผู้ใช้ปิดหน้าต่างเบราว์เซอร์หรือประเภทใน URL ใหม่
ในการหลีกเลี่ยงสิ่งนั้นคุณอาจต้องใช้ setTimeout () ของ Javascript บนหน้าเว็บทำการโทร AJAX ทุกสองสามวินาที (ขึ้นอยู่กับความเร็วที่คุณต้องการทราบหากผู้ใช้ออกไป)
ต้องขอบคุณService Workersมันเป็นไปได้ที่จะใช้วิธีการแก้ปัญหาที่คล้ายกับอดัมล้วนๆบนฝั่งไคลเอ็นต์โดยให้เบราว์เซอร์รองรับ หลีกเลี่ยงการร้องขอการเต้นของหัวใจ:
// The delay should be longer than the heartbeat by a significant enough amount that there won't be false positives
const liveTimeoutDelay = 10000
let liveTimeout = null
global.self.addEventListener('fetch', event => {
clearTimeout(liveTimeout)
liveTimeout = setTimeout(() => {
console.log('User left page')
// handle page leave
}, liveTimeoutDelay)
// Forward any events except for hearbeat events
if (event.request.url.endsWith('/heartbeat')) {
event.respondWith(
new global.Response('Still here')
)
}
})
setInterval(() => fetch('/heartbeat'), 5000)?
ในกรณีที่คุณต้องทำโค้ดแบบอะซิงโครนัส (เช่นการส่งข้อความไปยังเซิร์ฟเวอร์ที่ผู้ใช้ไม่ได้มุ่งเน้นไปที่หน้าของคุณตอนนี้) เหตุการณ์beforeunloadจะไม่ให้เวลากับรหัส async เพื่อให้ทำงาน ในกรณีของ async ฉันพบว่าvisibilitychangeและmouseleaveเหตุการณ์เป็นตัวเลือกที่ดีที่สุด เหตุการณ์เหล่านี้เริ่มต้นขึ้นเมื่อผู้ใช้เปลี่ยนแท็บหรือซ่อนเบราว์เซอร์หรือนำเคอร์เซอร์ออกจากขอบเขตหน้าต่าง
document.addEventListener('mouseleave', e=>{
//do some async code
})
document.addEventListener('visibilitychange', e=>{
if (document.visibilityState === 'visible') {
//report that user is in focus
} else {
//report that user is out of focus
}
})
สำหรับสิ่งที่คุ้มค่านี่คือสิ่งที่ฉันทำและอาจช่วยคนอื่นได้แม้ว่าบทความจะเก่า
PHP:
session_start();
$_SESSION['ipaddress'] = $_SERVER['REMOTE_ADDR'];
if(isset($_SESSION['userID'])){
if(!strpos($_SESSION['activeID'], '-')){
$_SESSION['activeID'] = $_SESSION['userID'].'-'.$_SESSION['activeID'];
}
}elseif(!isset($_SESSION['activeID'])){
$_SESSION['activeID'] = time();
}
JS
window.setInterval(function(){
var userid = '<?php echo $_SESSION['activeID']; ?>';
var ipaddress = '<?php echo $_SESSION['ipaddress']; ?>';
var action = 'data';
$.ajax({
url:'activeUser.php',
method:'POST',
data:{action:action,userid:userid,ipaddress:ipaddress},
success:function(response){
//alert(response);
}
});
}, 5000);
โทร Ajax ไปยัง activeUser.php
if(isset($_POST['action'])){
if(isset($_POST['userid'])){
$stamp = time();
$activeid = $_POST['userid'];
$ip = $_POST['ipaddress'];
$query = "SELECT stamp FROM activeusers WHERE activeid = '".$activeid."' LIMIT 1";
$results = RUNSIMPLEDB($query);
if($results->num_rows > 0){
$query = "UPDATE activeusers SET stamp = '$stamp' WHERE activeid = '".$activeid."' AND ip = '$ip' LIMIT 1";
RUNSIMPLEDB($query);
}else{
$query = "INSERT INTO activeusers (activeid,stamp,ip)
VALUES ('".$activeid."','$stamp','$ip')";
RUNSIMPLEDB($query);
}
}
}
ฐานข้อมูล:
CREATE TABLE `activeusers` (
`id` int(11) NOT NULL,
`activeid` varchar(20) NOT NULL,
`stamp` int(11) NOT NULL,
`ip` text
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
โดยทั่วไปทุกๆ 5 วินาที js จะโพสต์ไปยังไฟล์ php ที่จะติดตามผู้ใช้และที่อยู่ ip ของผู้ใช้ ผู้ใช้ที่ใช้งานอยู่เป็นเพียงบันทึกฐานข้อมูลที่มีการปรับปรุงการประทับเวลาของฐานข้อมูลภายใน 5 วินาที ผู้ใช้เก่าหยุดการอัปเดตเป็นฐานข้อมูล ที่อยู่ IP นั้นใช้เพื่อให้แน่ใจว่าผู้ใช้นั้นไม่เหมือนใครดังนั้น 2 คนบนเว็บไซต์ในเวลาเดียวกันไม่ได้ลงทะเบียนเป็น 1 ผู้ใช้
อาจไม่ใช่โซลูชันที่มีประสิทธิภาพที่สุด แต่ทำงานได้