如何使用Javascript判断浏览器标签页是否已经打开?

18

如何在纯/本机JavaScript中知道或检查两个浏览器标签页是否已经打开,如果这些标签页已经打开,用户将收到一个警报框或消息框,显示“该网址已经打开”等信息?这个浏览器标签页包含一个外部网站,我没有任何特权来操作或更改它。谢谢

示例URL:

yahoo.com and google.com

如果已经有针对yahoo.com和google.com的标签页打开,我想要向用户发出警告。

并且我想要使用tabCreate函数以以下方式打开URL:

tabCreate("http://maps.google.com/", "tabMapsPermanentAddress");
mean to open a new tab, it is use in creating chrome extension

window.open() 返回 ref,您可以在打开窗口之前检查它。var windowObjectReference = window.open(strUrl, strWindowName[, strWindowFeatures]); - Girish
像这样的 http://jsfiddle.net/vyhy9wbu/ 吗?它会提示用户该网址已经打开了吗? - User014019
1
我认为你想要看这个:http://jsfiddle.net/vyhy9wbu/1/ - Girish
6个回答

12

你可以使用以下类似的方法:

<!-- HTML -->
<a id="opener">Open window</a>

// JavaScript
var a = document.getElementById('opener'), w;        
a.onclick = function() {
  if (!w || w.closed) {
    w = window.open("https://www.google.com","_blank","menubar = 0, scrollbars = 0");
  } else {
    console.log('window is already opened');
  }
  w.focus();
};

这里是可工作的 jsBin | 更多关于 Window.open 方法的信息

如果您想要控制多个窗口,请使用下面的代码片段

<!-- HTML -->
<a href="https://www.google.com" class="opener">Open google.com</a> | 
<a href="http://www.yahoo.com" class="opener">Open yahoo.com</a> 

//JavaScript
window.onload = function(){
  var a = document.querySelectorAll('.opener'), w = [], url, random, i;
  for(i = 0; i < a.length; i++){
    (function(i){
      a[i].onclick = function(e) {
        if (!w[i] || w[i].closed) {
          url = this.href;
          random = Math.floor((Math.random() * 100) + 1); 
          w[i] = window.open(url, "_blank", random, "menubar = 0, scrollbars = 0");
        } else {
          console.log('window ' + url + ' is already opened');
        }
        e.preventDefault();
        w[i].focus();
      };
    })(i);
  }
};

这里是可工作的 jsBin

如果您不想让它们在单独的窗口中加载,只需排除此行即可。

random = Math.floor((Math.random()*100)+1);

并从下一行中删除random引用

w[i] = window.open(url, "_blank", random, "menubar=0,scrollbars=0");

顺带一提:如您所见,我们创建了两个带有第三方内容的窗口;您应该知道,无法从这些窗口中获取任何引用(指父级/打开者窗口)。


我该如何将您的代码与此代码http://jsfiddle.net/jjjs5wd3/3/(由Casey Chu提供)结合起来? - User014019
1
我明白了。但是如果我有两个URL,我想让用户弹出一个警告,告诉他们这些URL已经打开了怎么办? - User014019
@User014019 上面第一个解决方案的代码是正确的,但我发现在那个jsBin中w变量没有被声明;现在它可以工作了。此外,我添加了另一种解决方案,允许您控制多个窗口 - 您可以拥有尽可能多的窗口。如果有帮助,请告诉我。 - hex494D49
我在我的问题中添加了tabCreate()函数 :) - User014019
1
这是检查浏览器选项卡是否存在并刷新它的代码if (!w || w.closed) { // w = window w = window.open( route("yoururl"), '_blank' ); } else { console.log('window is already opened'); } w.focus(); w.location.href = route("yoururl"); - Chung Nguyen
显示剩余8条评论

7

一个基本的想法是将选项卡计数存储在cookie或localStorage中,在页面加载时递增,在页面卸载时递减:

if (+localStorage.tabCount > 0)
    alert('Already open!');
else
    localStorage.tabCount = 0;

localStorage.tabCount = +localStorage.tabCount + 1;
window.onunload = function () {
    localStorage.tabCount = +localStorage.tabCount - 1;
};

请在多个标签页中打开此fiddle进行尝试。

需要注意的是,这种技术相当脆弱。例如,如果由于某种原因浏览器崩溃,卸载处理程序将不会运行,它将失去同步。


我明白了。你能给我一个带有URL的实时示例吗? - User014019
与google.com类似,如果打开它,它将使用您的代码发出警报。请查看更新后的问题。 - User014019
3
当浏览器崩溃时,localStorage 中的值将被保留。tabCount 值将永远不会再次达到 0。 - Grzegorz Żur
当用户重定向到登录页面并返回页面时,这也是不可靠的。 - Sandip Subedi
页面刷新会增加选项卡计数。 - Rohit Kumar
在Safari/MacBook Air上测试,它总是会弹出“已经打开!”的提示。而在Google中,有时一个浏览器选项卡(tab)的数量(tabCount)大于1。 - step

4
Casey Chu的答案在页面没有崩溃之前运行良好。但是,下一次执行时,localStorage对象将使用非零值初始化tabCount。因此,更好的解决方案是将该值存储在会话cookie中。成功退出浏览器时,会话cookie将被删除。当浏览器崩溃时,会话cookie实际上将被保留,但幸运的是只有在下一次浏览器执行时才能看到。 sessionStorage对象对于每个选项卡都是不同的,因此不能用于共享选项卡计数。
这是使用js-cookie库的改进解决方案。
if (+Cookies.get('tabs') > 0)
    alert('Already open!');
else
    Cookies.set('tabs', 0);

Cookies.set('tabs', +Cookies.get('tabs') + 1);

window.onunload = function () {
        Cookies.set('tabs', +Cookies.get('tabs') - 1);
};

你可以使用 BroadcastChannel 来代替使用 cookies。 - Anderson Green

0

这个答案:https://dev59.com/UF4c5IYBdhLWcg3wLXrI#28230846 是一个不需要 Cookies/js-cookie 库的替代方案。它更适合我的需求。简而言之(完整说明请参见链接的答案):

$(window).on('storage', message_receive);

...

// use local storage for messaging. Set message in local storage and clear it right away
// This is a safe way how to communicate with other tabs while not leaving any traces
//
function message_broadcast(message)
{
    localStorage.setItem('message',JSON.stringify(message));
    localStorage.removeItem('message');
}


// receive message
//
function message_receive(ev)
{
    if (ev.originalEvent.key!='message') return; // ignore other keys
    var message=JSON.parse(ev.originalEvent.newValue);
    if (!message) return; // ignore empty msg or msg reset

    // here you act on messages.
    // you can send objects like { 'command': 'doit', 'data': 'abcd' }
    if (message.command == 'doit') alert(message.data);

    // etc.
}

0

我想分享一下这个内容,因为我希望我能有这样的东西。你可以自由使用它。

如果你想要一个解决方案来检查你是否是活动选项卡,而不需要 cookie,作为 React hook 工作,并且无论浏览器是否崩溃都能工作,你可以使用这个 useIsActiveTab webhook,它会返回 true 如果你是最近的活动选项卡/窗口。你也可以使用 activateTab 将自己设置为活动选项卡。

import { useEffect, useState } from 'react';

const CHARACTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const CHARACTERS_LENGTH = CHARACTERS.length;

function generateTabId() {
  let result = '';
  const prefix = 'TAB_';
  const length = 15;
  for (let i = 0; i < length - prefix.length; i++) {
    result += CHARACTERS.charAt(Math.floor(Math.random() * CHARACTERS_LENGTH));
  }
  if (prefix.includes('_')) {
    return `${prefix}${result}`;
  }
  return `${prefix}_${result}`;
};

const tabId = generateTabId();

export function activateTab(): void {
  localStorage.setItem('activeTab', tabId);
  const event = new Event('thisStorage');
  window.dispatchEvent(event);
}

export function useIsActiveTab(): boolean {
  const [isActiveTab, setIsActiveTab] = useState(false);
  useEffect(() => {
    setActiveTab();
    function updateIsActiveTab() {
      setIsActiveTab(checkIfActiveTab());
    }
    window.addEventListener('storage', updateIsActiveTab);
    window.addEventListener('thisStorage', updateIsActiveTab);
    updateIsActiveTab();
    return () => {
      window.removeEventListener('storage', updateIsActiveTab);
      window.removeEventListener('thisStorage', updateIsActiveTab);
    };
  }, []);
  return isActiveTab;
}

function checkIfActiveTab(): boolean {
  const activeTab = localStorage.getItem('activeTab');
  if (!activeTab) {
    console.error('localStorage.activeTab is not set');
    return true;
  }
  if (activeTab === tabId) {
    return true;
  }
  return false;
}

function setActiveTab(): void {
  localStorage.setItem('activeTab', tabId);
}

0
enter code here// Check if the 'tabs' session cookie exists
    if (!Cookies.get('tabs')) {
        Cookies.set('tabs', 0, { expires: 0 }); // Expires when the browser is closed
    }
    // Check if the session cookie exists and its value
    if (+Cookies.get('tabs') > 0) {
        `enter code here`alert('Already open!');
    } else {
        Cookies.set('tabs', 0, { expires: 1 }); // Expires after one day (adjust as needed)
    }
    // Increment the 'tabs' cookie value when opening a new tab
    Cookies.set('tabs', +Cookies.get('tabs') + 1);

    // Decrement the 'tabs' cookie value when closing a tab
    window.onunload = function () {
        Cookies.set('tabs', +Cookies.get('tabs') - 1);
    };

    // Decrement the 'tabs' cookie value when the tab is being closed
    window.addEventListener('beforeunload', function () {
        Cookies.set('tabs', +Cookies.get('tabs') - 1);
    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接