Javascript 在chrome扩展中保持页面操作的状态

Javascript 在chrome扩展中保持页面操作的状态,javascript,google-chrome,google-chrome-extension,Javascript,Google Chrome,Google Chrome Extension,因此,我有以下代码: var clicks = 0; // click counter // Make sure this only runs on facebook chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { if (tab.url.indexOf("facebook.com") > -1) { chrome.pageAction.show(tabId); }

因此,我有以下代码:

var clicks = 0; // click counter

// Make sure this only runs on facebook
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (tab.url.indexOf("facebook.com") > -1) {
        chrome.pageAction.show(tabId);
    }
});

// Called when the user clicks on the page action.
chrome.pageAction.onClicked.addListener(function(tab) {
  if (clicks == 0) {
    chrome.pageAction.setIcon({path: "dontlike.png", tabId: tab.id}); // Update icon
    chrome.pageAction.setTitle({title: "idontlike", tabId: tab.id}); // Update title
    chrome.tabs.executeScript({ // Hide like buttons
      code: 'var like = document.getElementsByClassName("UFILikeLink"); for (index = 0; index < like.length; ++index) { like[index].style.display="none"; }'
    });
  } 
  else {
    chrome.pageAction.setIcon({path: "like.png", tabId: tab.id}); // Update icon
    chrome.pageAction.setTitle({title: "like", tabId: tab.id}); // Update title
    chrome.tabs.executeScript({ // Show like buttons
      code: 'var like = document.getElementsByClassName("UFILikeLink"); for (index = 0; index < like.length; ++index) { like[index].style.display=""; }'
    });
  }

  // wrap coutner around
  clicks++;
  if (clicks > 1)
    clicks = 0;
});
对于一个chrome扩展,当点击pageaction图标时,它会隐藏facebook上的所有类似按钮。这是有效的;但是,任何时候加载新的facebook url时,扩展的状态都会丢失,例如,如果按钮处于不喜欢模式,则隐藏所有喜欢,如果我转到新页面,则会重置为喜欢模式

我有一个想法,就是使用click计数器来持久化扩展的状态,并使用如下内容使代码更具功能性

var clicks = 0; // click counter

function like() {
  chrome.pageAction.setIcon({path: "like.png", tabId: tab.id}); // Update icon
  chrome.pageAction.setTitle({title: "like", tabId: tab.id}); // Update title
  chrome.tabs.executeScript({ // Show like buttons
    code: 'var like = document.getElementsByClassName("UFILikeLink"); for (index = 0; index < like.length; ++index) { like[index].style.display="none"; }'
  });

  clicks++;
  if (clicks > 1) {
    clicks = 0;
  }
}

function dislike() {
  chrome.pageAction.setIcon({path: "like.png", tabId: tab.id}); // Update icon
  chrome.pageAction.setTitle({title: "like", tabId: tab.id}); // Update title
  chrome.tabs.executeScript({ // Show like buttons
    code: 'var like = document.getElementsByClassName("UFILikeLink"); for (index = 0; index < like.length; ++index) { like[index].style.display=""; }'
  });

  clicks++;
  if (clicks > 1) {
    clicks = 0;
  }
}

// Make sure this only runs on facebook
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (tab.url.indexOf("facebook.com") > -1) {
      chrome.pageAction.show(tabId);
      if (clicks == 0) {
        like();
      } 
      else {
        dislike();
      }
    }
});

// Called when the user clicks on the page action.
chrome.pageAction.onClicked.addListener(function(tab) {
  if (clicks == 0) {
    like();
  } 
  else {
    dislike();
  }
});
但是,当我点击页面操作图标时,代码根本不起作用,什么也没有发生,chrome控制台中也没有出现错误消息

我是JS和Chrome扩展的新手。有没有一种简单的方法来保持扩展的状态,还有更好的方法来执行隐藏所有按钮所需的脚本


谢谢大家!

当扩展使用非持久性后台页面时,它会在约5秒的不活动后卸载。每次重新加载时,代码都会再次运行,所有变量都会重新初始化,从而丢失以前的状态

解决方案是将状态存储在localStorage中,它不需要manifest.json中的任何附加权限:

初始化:

var clicks = localStorage.clicks || 0; // click counter
切换和存储不需要++并且如果:


该值将被字符串化并存储为0或1,但对于上述算法而言,这不是问题。

当扩展使用非持久性背景页时,它将在约5秒的不活动后卸载。每次重新加载时,代码都会再次运行,所有变量都会重新初始化,从而丢失以前的状态

解决方案是将状态存储在localStorage中,它不需要manifest.json中的任何附加权限:

初始化:

var clicks = localStorage.clicks || 0; // click counter
切换和存储不需要++并且如果:


该值将被字符串化并存储为0或1,但对于上述算法来说这不是问题。

chrome extension中的状态问题可以有几个答案。选择取决于形势。我对你的理解是,你只有两种状态,所以我会给你一些想法

1.持久化背景脚本 默认情况下,后台脚本在chrome启动时加载,因此它在chrome的整个执行过程中一直存在,直到用户显式关闭chrome为止。结合内容脚本,您可以拥有一个状态完整的系统

因此,您可以使用此后台脚本在执行期间保存状态,并将更改通知侦听内容脚本:

background.js

然后,您可以通过将内容脚本添加到manifest.json文件,将其注入所有facebook页面

它将自动将contentScipt.js脚本注入以https://www.facebook.com.

contenScript.js //为每个州采取的行动 函数状态0操作 { //对状态0执行所需操作 }

在这里,onMessage处理程序将在加载时第一次被调用,然后每次后台更改状态时被调用

请注意,状态将在chrome启动时重置

2.铬存储 您可以使用chrome.storage API来管理状态。主要的一点是,状态将被保存,并且不会在chrome启动时重置

要做到这一点,您有非常相同的背景代码:

chrome.pageAction.onClicked.addListener(function(tab) {
    chrome.storage.local.get("state", function(result)
    {
        //First initialisation of the state in the local storage
        if(result.state == null)
        {
            chrome.storage.local.set({state: 0});
            state0Actions(); //Do what you want
        }
        else if (result.state == 0) {
            result.state = 1;
            state0Actions(); //Do what you want
        } 
        else {
            result.state = 0;
            state1Actions(); //Do what you want
        }

        //Save the new state to the storage
        chrome.storage.set({state: result.state});
    }
});
内容脚本将侦听本地存储的更改,而不是等待来自后台页面的更新通知:

//the actions to do for each states
function state0Actions()
{
    //Do what you want for the state 0
}

function state1Actions()
{
    //Do what you want for the state 1
}

chrome.storage.local.onChanged.addListener(function(changes, areaName)
{
    if(areaName != "local" || changes.state == null) return;

    switch(changes.state)
    {
        case 0 : state0Actions(); break;
        case 1 : state1Actions(); break;
    }
})

chrome.storage.local.get("state", function(result){
    if(result.state == null) state0Actions(); //Do what you want if the state is not yet initialised
    else if (result.state == 0) state0Actions(); //Do what you want
    else if (result.state == 1) state1Actions(); //Do what you want
})
您还可以使用chrome.storage.sync而不是chrome.storage.local与所有用户设备共享状态

这是一种玩弄国家的方式。您必须比较哪些更适合您的用例。我写的代码没有经过测试,它们只是用来说明我的解释的示例


别忘了检查chrome extension中的状态问题可以有几个答案。选择取决于形势。我对你的理解是,你只有两种状态,所以我会给你一些想法

1.持久化背景脚本 默认情况下,后台脚本在chrome启动时加载,因此它在chrome的整个执行过程中一直存在,直到用户显式关闭chrome为止。结合内容脚本,您可以拥有一个状态完整的系统

因此,您可以使用此后台脚本在执行期间保存状态,并将更改通知侦听内容脚本:

background.js

然后,您可以通过将内容脚本添加到manifest.json文件,将其注入所有facebook页面

它将自动将contentScipt.js脚本注入以https://www.facebook.com.

contenScript.js //为每个州采取的行动 函数状态0操作 { //对状态0执行所需操作 }

在这里,onMessage处理程序将在第一次加载时被调用,然后在每次加载后台时被调用 改变状态

请注意,状态将在chrome启动时重置

2.铬存储 您可以使用chrome.storage API来管理状态。主要的一点是,状态将被保存,并且不会在chrome启动时重置

要做到这一点,您有非常相同的背景代码:

chrome.pageAction.onClicked.addListener(function(tab) {
    chrome.storage.local.get("state", function(result)
    {
        //First initialisation of the state in the local storage
        if(result.state == null)
        {
            chrome.storage.local.set({state: 0});
            state0Actions(); //Do what you want
        }
        else if (result.state == 0) {
            result.state = 1;
            state0Actions(); //Do what you want
        } 
        else {
            result.state = 0;
            state1Actions(); //Do what you want
        }

        //Save the new state to the storage
        chrome.storage.set({state: result.state});
    }
});
内容脚本将侦听本地存储的更改,而不是等待来自后台页面的更新通知:

//the actions to do for each states
function state0Actions()
{
    //Do what you want for the state 0
}

function state1Actions()
{
    //Do what you want for the state 1
}

chrome.storage.local.onChanged.addListener(function(changes, areaName)
{
    if(areaName != "local" || changes.state == null) return;

    switch(changes.state)
    {
        case 0 : state0Actions(); break;
        case 1 : state1Actions(); break;
    }
})

chrome.storage.local.get("state", function(result){
    if(result.state == null) state0Actions(); //Do what you want if the state is not yet initialised
    else if (result.state == 0) state0Actions(); //Do what you want
    else if (result.state == 1) state1Actions(); //Do what you want
})
您还可以使用chrome.storage.sync而不是chrome.storage.local与所有用户设备共享状态

这是一种玩弄国家的方式。您必须比较哪些更适合您的用例。我写的代码没有经过测试,它们只是用来说明我的解释的示例



别忘了检查一下

我还不太明白你要做什么。我的理解是,你必须选择一种模式:一种是隐藏相似按钮的模式,另一种是显示相似按钮的模式。你可以通过点击页面操作按钮在状态和状态之间切换。我说得对吗?@EmrysMyrooin没错!所以我已经给出了一个答案,我认为对于你的用例来说,第二个解决方案是最好的,因为它可以在chrome会话中保存状态。我还不太清楚你要做什么。我的理解是,你必须选择一种模式:一种是隐藏相似按钮的模式,另一种是显示相似按钮的模式。你可以通过点击页面操作按钮在状态和状态之间切换。我说得对吗?@EmrysMyrooin没错!所以我给出了一个答案,我认为对于您的使用案例来说,第二个解决方案是最好的,因为它可以在chrome会话上保存状态为什么是localStorage而不是chrome.storage?因为1个chrome.storage需要额外的权限,2个localStorage就足够了。公平地说,该权限不会触发警告,因此可以随时删除/添加该权限,而不会产生任何可见效果。还要注意的是,localStorage只存储字符串,所以您在那里玩fire,依赖于松散的键入。好吧,给定的任务没有fire,所以完全可以,不需要过度复杂。我认为隐式类型转换是过度复杂的。。我刚刚注意到你的最后一句话,是的,只要开发人员知道这一点就可以了。为什么是localStorage而不是chrome.storage?因为1个chrome.storage需要额外的权限,2个localStorage就足够了。公平地说,该权限不会触发警告,因此,它可以在任何时候删除/添加,而不会产生任何可见的效果。还要注意的是,localStorage只存储字符串,所以您在那里玩fire,依赖于松散的键入。好吧,给定的任务没有fire,所以完全可以,不需要过度复杂。我认为隐式类型转换是过度复杂的。。我刚刚注意到你的最后一句话,所以是的,只要开发人员知道这一点就可以了。我很难让这两个解决方案都起作用。我修复了解决方案1的部分代码,将侦听器添加到onMessage,并将其更改为chrome.runtime.onMessage,但这也不起作用。使用第二个选项时,我无法使我的函数调用正常工作,因为在上下文脚本中调用它们时,没有pageAction的侦听器。不知道如何解决此问题。使用新代码发布新问题或编辑问题:-@glcohen我已为第一个解决方案更正了我的帖子。但是对于第二个,您必须将页面操作相关的代码放在后台脚本中。这里的内容脚本只是用来修改页面的DOM,在您的例子中是隐藏所有类似按钮。我很难让这两种解决方案都起作用。我修复了解决方案1的部分代码,将侦听器添加到onMessage,并将其更改为chrome.runtime.onMessage,但这也不起作用。使用第二个选项时,我无法使我的函数调用正常工作,因为在上下文脚本中调用它们时,没有pageAction的侦听器。不知道如何解决此问题。使用新代码发布新问题或编辑问题:-@glcohen我已为第一个解决方案更正了我的帖子。但是对于第二个,您必须将页面操作相关的代码放在后台脚本中。这里的内容脚本仅用于修改页面的DOM,在您的例子中是隐藏所有类似按钮。
//the actions to do for each states
function state0Actions()
{
    //Do what you want for the state 0
}

function state1Actions()
{
    //Do what you want for the state 1
}

chrome.storage.local.onChanged.addListener(function(changes, areaName)
{
    if(areaName != "local" || changes.state == null) return;

    switch(changes.state)
    {
        case 0 : state0Actions(); break;
        case 1 : state1Actions(); break;
    }
})

chrome.storage.local.get("state", function(result){
    if(result.state == null) state0Actions(); //Do what you want if the state is not yet initialised
    else if (result.state == 0) state0Actions(); //Do what you want
    else if (result.state == 1) state1Actions(); //Do what you want
})