เบราว์เซอร์ sessionStorage แชร์ระหว่างแท็บหรือไม่


151

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

ฉันจะแชร์sessionStorageค่าระหว่างแท็บเบราว์เซอร์ทั้งหมดกับแอปพลิเคชันของฉันได้อย่างไร

กรณีการใช้งาน: ใส่ค่าในที่เก็บข้อมูลบางอย่างเก็บค่านั้นไว้ในแท็บเบราว์เซอร์ทั้งหมดและล้างค่าหากปิดแท็บทั้งหมด

if (!sessionStorage.getItem(key)) {
    sessionStorage.setItem(key, defaultValue)
}

9
มันแปลกสำหรับฉันที่สิ่งนี้ถูกปิดเหมือนสำเนา เสนอชื่อเพื่อเปิดใหม่ หัวข้ออื่น ๆ เกี่ยวกับ "วิธีการสื่อสารระหว่างหลายแท็บ" ซึ่งฟังดูแตกต่างและแตกต่างกันเมื่อฉันเริ่มอ่านหัวข้ออื่น ๆ
KajMagnus

เป็นไปได้ที่จะใช้คุกกี้หรือไม่ ซึ่งพฤติกรรมเช่นนั้นโดยค่าเริ่มต้น? ( แต่แน่นอน - สำหรับการรับและการกระทำชุดที่พวกเขาจะต้องการดำเนินการต่อไป) developer.mozilla.org/en-US/docs/Web/API/Document/cookie
lingar

คำตอบ:


133

คุณสามารถใช้ localStorage และ "storage" eventListener เพื่อถ่ายโอนข้อมูล sessionStorage จากแท็บหนึ่งไปยังอีกแท็บหนึ่ง

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

// transfers sessionStorage from one tab to another
var sessionStorage_transfer = function(event) {
  if(!event) { event = window.event; } // ie suq
  if(!event.newValue) return;          // do nothing if no value to work with
  if (event.key == 'getSessionStorage') {
    // another tab asked for the sessionStorage -> send it
    localStorage.setItem('sessionStorage', JSON.stringify(sessionStorage));
    // the other tab should now have it, so we're done with it.
    localStorage.removeItem('sessionStorage'); // <- could do short timeout as well.
  } else if (event.key == 'sessionStorage' && !sessionStorage.length) {
    // another tab sent data <- get it
    var data = JSON.parse(event.newValue);
    for (var key in data) {
      sessionStorage.setItem(key, data[key]);
    }
  }
};

// listen for changes to localStorage
if(window.addEventListener) {
  window.addEventListener("storage", sessionStorage_transfer, false);
} else {
  window.attachEvent("onstorage", sessionStorage_transfer);
};


// Ask other tabs for session storage (this is ONLY to trigger event)
if (!sessionStorage.length) {
  localStorage.setItem('getSessionStorage', 'foobar');
  localStorage.removeItem('getSessionStorage', 'foobar');
};

ฉันทดสอบมันด้วยโครเมี่ยม, ff, ซาฟารี, คือ 11, 10, ie9

วิธีนี้ "ควรทำงานใน IE8" แต่ฉันไม่สามารถทดสอบได้เนื่องจาก IE ของฉันหยุดทำงานทุกครั้งที่ฉันเปิดแท็บ .... แท็บใด ๆ ... บนเว็บไซต์ใด ๆ (IE ดีดี) PS: คุณจะต้องมี JSON shim ด้วยถ้าคุณต้องการ IE8 เช่นกัน :)

เครดิตไปที่บทความเต็มรูปแบบนี้: http://blog.guya.net/2015/06/12/sharing-sessionstorage-between-tabs-for-secure-multi-tab-authentication/


2
วิธีนี้น่าเชื่อถือเพียงใด? เนื่องจากเป็นไปตามเหตุการณ์จึงมีโอกาสที่จะพลาดกิจกรรมหรือไม่
vivek241

2
จากคำตอบที่นี่ฉันสร้างห้องสมุดบน localStorage และ sessionStorage เพื่อทำให้สิ่งนี้ง่ายขึ้น ดังนั้นตอนนี้คุณเพียงโทรไปที่ storageManager.saveSyncedSessionData ('data', 'key'); หรือ storageManager.savePermanentData ('data', 'key'); ฯลฯ ขึ้นอยู่กับสิ่งที่คุณต้องการ รหัสเต็มอยู่ที่นี่: ebenmonney.com/blog/…
adentum

@ vivek241 โซลูชันใช้งานได้ดีสำหรับฉันเมื่อขนาดไฟล์ JS เล็กลงและ "สคริปต์โซลูชัน" ที่ระบุด้านบนถูกโหลดเป็นสคริปต์แรกในหน้าเว็บ เมื่อไฟล์ JS ของฉันขยายใหญ่เกินไปพูดมากกว่า 1,000 บรรทัดขึ้นไปทันใดนั้นก็หยุดทำงานและลบคุกกี้ของฉันและข้อมูล localStorage ที่เฉพาะเจาะจงเช่นกัน ฉันไม่แน่ใจว่านี่เป็นโซลูชั่นที่น่าเชื่อถือหรือข้ามเบราว์เซอร์ที่สามารถพึ่งพาได้ ดังนั้นให้เขียนตรรกะทั้งหมดใหม่เพื่อแก้ไขปัญหาด้วยคุกกี้เพียงอย่างเดียว
webblover

4
เหตุการณ์จะไม่ถูกเรียกในแท็บที่เปิดก่อนหน้านี้ทั้งหมดหรือไม่
Dtipson

3
ดูเหมือนว่าBroadcastChannelตอนนี้เป็นเครื่องมือที่ดีสำหรับการทำเช่นนี้ Developers.google.com/web/updates/2016/09/broadcastchannel
alexbea

71

ใช้sessionStorageสำหรับสิ่งนี้เป็นไปไม่ได้

จากเอกสาร MDN

การเปิดหน้าเว็บในแท็บหรือหน้าต่างใหม่จะทำให้เซสชันใหม่เริ่มต้น

ซึ่งหมายความว่าคุณไม่สามารถแชร์ระหว่างแท็บได้ด้วยเหตุนี้คุณควรใช้ localStorage


8
ตกลงฉันเข้าใจแล้ว แต่จะล้าง localStorage ได้อย่างไรเมื่อปิดแท็บเบราว์เซอร์ทั้งหมด
Vladimir Gordienko

คุณสามารถเปลี่ยนคุกกี้เอกสารเพื่อpath='/'บังคับให้ล้างเมื่อปิดหน้าต่างเบราว์เซอร์ แต่ตอนนี้ฉันยังไม่รู้เลย
Henrik Andersson

ตกลงฉันจะขุดลึกและแจ้งให้คุณทราบหากฉันพบวิธีการแก้ปัญหาให้คิดว่าตอนนี้มันเป็นไปไม่ได้))
Vladimir Gordienko

5
@Amol ใช่ แต่ฉันไม่สามารถให้รหัสใด ๆ แล้วมันอยู่ไกลแล้ว นี่เป็นวิธีแก้ปัญหาที่น่าเกลียด แต่มันก็ใช้ได้ผลสำหรับฉันอย่างสมบูรณ์ กุญแจสำคัญคือการรักษาตัวนับ tabsOpened ในที่จัดเก็บในตัวเครื่องและเพิ่มเมื่อการโหลดหน้าเว็บ แต่ลดลงเมื่อยกเลิกการโหลดหน้า ดังนั้นเมื่อหน้ายกเลิกการโหลดและ tabsOpen == 1 แท็บสุดท้ายของมันและเราสามารถล้างทุกสิ่ง มีบางสิ่งเล็กน้อยที่ฉันต้องจัดการ แต่จำไม่ได้ว่าอะไรกันแน่ หวังว่ามันจะช่วยคุณได้!
Vladimir Gordienko

1
@VladimirGordienko เกิดอะไรขึ้นถ้าเหตุการณ์การยกเลิกการโหลดที่ลบlocalStorageข้อมูลเกิดขึ้นเพราะมีคนนำทางไปยังโดเมนอื่นในแท็บเดียวกัน ดูเหมือนว่าฉันจะลบlocalStorageข้อมูลไม่ถูกต้อง- แท็บไม่ได้ปิดและถ้าบุคคลนำทางกลับ s / เขาจะต้องการข้อมูลอีกครั้งใช่ไหม อย่างไรก็ตามมันเป็นวิธีการที่น่าสนใจไม่คิดอย่างนั้น: -)
KajMagnus

9
  1. คุณก็สามารถใช้และจำไว้ว่าวันที่มันถูกสร้างขึ้นเป็นครั้งแรกในlocalStorage session cookieเมื่อlocalStorage"เซสชั่น" เก่ากว่าค่าของคุกกี้แล้วคุณสามารถล้างlocalStorage

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

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


9

การดูพื้นที่อื่นจริง ๆ ถ้าคุณเปิดด้วย _blank มันจะเก็บ sessionStorage ไว้ตราบเท่าที่คุณเปิดแท็บเมื่อพาเรนต์เปิดอยู่:

ในลิงค์นี้มี jsfiddle ที่ดีสำหรับทดสอบ sessionStorage ในหน้าต่างใหม่ไม่ว่างเปล่าเมื่อติดตามลิงก์ที่มี target = "_ blank"


0

โซลูชันของฉันที่ไม่มี sessionStorage ที่สามารถถ่ายโอนผ่านแท็บได้คือการสร้าง localProfile และแก้ไขตัวแปรนี้ หากตัวแปรนี้ถูกตั้งค่าไว้ แต่ตัวแปร sessionStorage ของฉันไม่ทำงานไปข้างหน้าและกำหนดค่าเริ่มต้นใหม่ เมื่อผู้ใช้ออกจากหน้าต่างปิดปิดทำลายตัวแปร localStorage นี้


-14

นี่เป็นวิธีการป้องกันการตัดเซสชันระหว่างแท็บเบราว์เซอร์สำหรับแอปพลิเคชัน Java สิ่งนี้จะใช้ได้กับ IE (JSP / Servlet)

  1. ในหน้า JSP แรกของคุณเหตุการณ์ onload เรียก servlet (ajex call) เพื่อตั้งค่า "window.title" และตัวติดตามเหตุการณ์ในเซสชัน (เพียงตัวแปรจำนวนเต็มที่ตั้งเป็น 0 ครั้งแรก)
  2. ตรวจสอบให้แน่ใจว่าไม่มีหน้าอื่น ๆ ตั้งค่า window.title
  3. หน้าทั้งหมด (รวมถึงหน้าแรก) เพิ่มจาวาสคริปต์เพื่อตรวจสอบชื่อหน้าต่างเมื่อการโหลดหน้าเสร็จสมบูรณ์ หากไม่พบชื่อเรื่องให้ปิดหน้า / แท็บปัจจุบัน (ให้แน่ใจว่าได้เลิกทำฟังก์ชั่น "window.unload" เมื่อสิ่งนี้เกิดขึ้น)
  4. ตั้งค่าหน้าหน้าต่างให้โหลดเหตุการณ์สคริปต์ java (สำหรับทุกหน้า) เพื่อจับภาพเหตุการณ์การรีเฟรชหน้าหากมีการรีเฟรชหน้าแล้วให้โทรเซิร์ฟเล็ตเพื่อรีเซ็ตตัวติดตามเหตุการณ์

1) หน้าแรก JS

BODY onload="javascript:initPageLoad()"

function initPageLoad() {
    var xmlhttp;

    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }

    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {                           var serverResponse = xmlhttp.responseText;
            top.document.title=serverResponse;
        }
    };
                xmlhttp.open("GET", 'data.do', true);
    xmlhttp.send();

}

2) JS ทั่วไปสำหรับทุกหน้า

window.onunload = function() {
    var xmlhttp;
    if (window.XMLHttpRequest) {
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {             
            var serverResponse = xmlhttp.responseText;              
        }
    };

    xmlhttp.open("GET", 'data.do?reset=true', true);
    xmlhttp.send();
}

var readyStateCheckInterval = setInterval(function() {
if (document.readyState === "complete") {
    init();
    clearInterval(readyStateCheckInterval);
}}, 10);
function init(){ 
  if(document.title==""){   
  window.onunload=function() {};
  window.open('', '_self', ''); window.close();
  }
 }

3) web.xml - การแมปเซิร์ฟเล็ต

<servlet-mapping>
<servlet-name>myAction</servlet-name>
<url-pattern>/data.do</url-pattern>     
</servlet-mapping>  
<servlet>
<servlet-name>myAction</servlet-name>
<servlet-class>xx.xxx.MyAction</servlet-class>
</servlet>

4) รหัส servlet

public class MyAction extends HttpServlet {
 public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws IOException {
    Integer sessionCount = (Integer) request.getSession().getAttribute(
            "sessionCount");
    PrintWriter out = response.getWriter();
    Boolean reset = Boolean.valueOf(request.getParameter("reset"));
    if (reset)
        sessionCount = new Integer(0);
    else {
        if (sessionCount == null || sessionCount == 0) {
            out.println("hello Title");
            sessionCount = new Integer(0);
        }
                          sessionCount++;
    }
    request.getSession().setAttribute("sessionCount", sessionCount);
    // Set standard HTTP/1.1 no-cache headers.
    response.setHeader("Cache-Control", "private, no-store, no-cache, must-                      revalidate");
    // Set standard HTTP/1.0 no-cache header.
    response.setHeader("Pragma", "no-cache");
} 
  }

3
คำถามนี้เกี่ยวกับจาวาสคริปต์มันไม่มีส่วนเกี่ยวข้องกับจาวาสคริปต์
victorpacheco3107

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