2015-07-20 61 views
0

我有一個單一元素的簡單頁面,其中id="test"。我做了一個簡單的擴展,內容如下腳本:自定義DOM屬性在擴展中不可見?

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) { 
    var elem = document.getElementById("test"); 
    console.log(test.value); 
    test.value = 3; 
}); 

現在,如果我點擊分機鍵,它打印undefined,然後保持打印3。但是,如果我嘗試從控制檯訪問這個值,它仍然是未定義的,並且改變它不影響擴展打印的內容。有什麼方法可以從擴展中實際訪問這個值嗎?

更新:好吧我發現擴展運行在一個單獨的環境中,不會與主腳本共享'expandos',所以我需要在實際頁面中注入一個腳本來做到這一點。

+1

你的意思是console.log(elem.value)?擴展肯定能夠做到這一點。 – ak2ln

回答

0

Content scripts執行在一個特殊的環境中,稱爲孤立的世界。他們可以訪問他們注入的頁面的DOM,但不能訪問頁面創建的任何JavaScript變量或函數。它會查看每個內容腳本,就好像其上運行的頁面上沒有執行其他JavaScript一樣。反過來也是如此:在頁面上運行的JavaScript不能調用任何函數或訪問由content scripts定義的任何變量。

儘管content scripts的執行環境和託管它們的頁面彼此隔離,但它們共享對頁面DOM的訪問。如果頁面希望與內容腳本進行通信(或通過內容腳本使用擴展名),則必須通過共享DOM進行通信。

  1. 使用window.postMessage

在內容腳本 -

var port = chrome.runtime.connect(); 

    window.addEventListener("message", function(event) { 
     // We only accept messages from ourselves 
     if (event.source != window) 
     return; 

     if (event.data.type && (event.data.type == "FROM_PAGE")) { 
     console.log("Content script received: " + event.data.text); 
     port.postMessage(event.data.text); 
     } 
    }, false); 

在您的網頁腳本 -

document.getElementById("theButton").addEventListener("click", 
    function() { 
    window.postMessage({ type: "FROM_PAGE", text: "Hello from the webpage!" }, "*"); 
}, false); 
  • In在你的頁面jecting腳本:
  • 在內容腳本 -

    function main() { 
         var elem = document.getElementById("test"); 
         console.log(test.value); 
         test.value = 3; 
        } 
    var script = document.createElement('script'); 
    script.appendChild(document.createTextNode('('+ main +')();')); 
    (document.body || document.head).appendChild(script); 
    
  • 創建自定義事件
  • 在這兩種注射或您的內容腳本添加了一個事件監聽器:

    document.addEventListener('yourCustomEvent', function (e) 
    { 
        var data=e.detail; 
        console.log("received "+data); 
    }); 
    

    在另一邊(內容或注入腳本)調用事件:

    var data="anything"; 
    var evt=document.createEvent("CustomEvent"); 
    evt.initCustomEvent("yourCustomEvent", true, true, data); 
    document.dispatchEvent(evt); 
    
    +0

    其中一半是從https://developer.chrome.com/extensions/content_scripts複製的 –

    0

    一件事,絕對的元素頁面,擴展上下文之間共享是data-*屬性。

    您可以通過.dataset接口對它們進行:

    chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) { 
        var elem = document.getElementById("test"); 
        console.log(test.dataset.value); 
        test.dataset.value = 3; // will become "3" 
    }); 
    

    這將對應於data-value="3"屬性在DOM元素上。

    更一般地,

    function storeValue(id, key, value) { 
        var element = document.getElementById(id); 
        if(!element) throw Error("Element #" + id = " not found"); 
        element.dataset[key] = JSON.stringify(value); 
    } 
    
    function readValue(id, key) { 
        var element = document.getElementById(id); 
        if(!element) throw Error("Element #" + id = " not found"); 
        var value = element.dataset[key]; 
        if(typeof value == "undefined") return undefined; 
        else return JSON.parse(value); 
    } 
    
    storeValue("test", "value", 3); 
    console.log(readValue("test", "value")); 
    

    我添加了序列化/反序列化,因爲屬性只能是字符串。

    相關問題