簡體   English   中英

Chrome開發者工具-通過重新加載頁面記住所選元素

[英]Chrome Dev Tools - Remembering the selected element through page reload

我正在構建自己的類型的Chrome開發工具(檢查元素),該工具也將以使用JavaScript的Chrome擴展程序的形式出現。 我希望它具有與Chrome開發者工具類似的功能,但我發現其中之一很難揭露他們是如何做到的。

基本上,當您右鍵單擊任何元素並單擊“檢查元素”時,它將打開開發工具(如果尚未打開),並將鼠標懸停在您的右鍵單擊定位的HTML元素上。

我要復制的一點是,當刷新頁面的同時仍在開發工具中選擇了元素,它將重新加載所有HTML並直接轉到在重新加載之前在開發工具中選擇的元素。

如果不清楚,這就是我的意思:

HTML:

<div class="1">
    <div class="2">
        <div class="3"></div>
    </div>
</div>

如果我將鼠標懸停在類別為“ 3”的div上並刷新了頁面,則Chrome開發人員工具知道可以使用突出顯示該確切div的開發人員工具進行重新加載。 即使存在多個具有該類或類似結構的div,它也始終會懸停在正確的位置上。

誰知道這里最好的方法是否是擁有一個大的if語句,該語句查找元素的某些特征,例如理想的id,但是如果元素沒有id(例如周圍元素或唯一元素),還會查找大量回退與該元素關聯的類/屬性?

我曾嘗試搜索“ Chrome擴展程序節點選擇器”或類似的變體,但無法找到任何信息。

已經存在一個非常好的“檢查元素”擴展,您可以在這里找到。 但是,它不支持保存檢查的元素。 但是,由於這是一個賞金問題,我可以給您一些提示,以將其改進為可行的解決方案。

我在這里看到的主要問題是“序列化”元素。 您可以在此處找到有關此主題的好答案。 (另請參見小提琴 )它基本上可以概括為“使用ID查找最近的祖先,並向下跟蹤到被檢查元素的路徑”。 在您的情況下,可能是:

tracePath: function (element, result) {
  if (element.id !== '') {
    result.push({
      id: element.id
    });
    return;
  }
  if (element === document.body) {
    result.push({
      tag: element.tagName
    });
    return;
  }

  var siblings = element.parentNode.childNodes;
  for (var i = 0; i < siblings.length; ++i) {
    var sibling = siblings[i];
    if (sibling === element) {
      result.push({
        index: i,
        tag: element.tagName
      });
      return this.tracePath(element.parentNode, result);
    }
  }
},

上面只是存儲了反序列化期間要遵循的節點數組:

find: function (path) {
  var element;
  while (path.length) {
    var current = path.pop();

    if (!current) return element;
    if (current.id) element = document.getElementById(current.id);
    else if (element) {
      if (current.index < element.childNodes.length && current.tag === element.childNodes[current.index].tagName)
        element = element.childNodes[current.index];
      else
        return;
    } else {
      var matches = document.getElementsByTagName(current.tag);
      if (matches.length)
          element = matches[0];
    }
  }
  return element;
},

一旦這兩個,我們只需要存儲/加載選擇的方法:

store: function (path) {
  var selection = Object.create({});
  selection[window.location.href] = path;
  chrome.storage.local.set(selection, function () {
    if (chrome.runtime.lastError) {
      console.error(chrome.runtime.lastError)
    }
  })
},

並加載:

load: function () {
  var self = this, key = window.location.href;
  chrome.storage.local.get(key, function (found) {
    if (chrome.runtime.lastError) {
      console.error(chrome.runtime.lastError)
    } else if (found && found[key]) {
      var path = found[key],
        element = Util.find(path);

      if (element) {
        // zoom into inspected element
        element.scrollIntoView();
        // add selection to Inspector instance
        self.$selection = element;
        // function similar to layout() - highlights inspected element
        self.select();
      }
    }
  })
}

然后,您可以編寫一個突出顯示功能,例如select以突出顯示被檢查的元素,類似於已經存在的突出標尺的layout

單擊該元素即可完成保存:

registerEvents: function() {
  ...
  document.addEventListener('click', function () {
      var path = [];
      Util.tracePath(this.$target, path);
      this.$selection = this.$target;
      this.select(true);
      this.storeSelection(path);
  }.bind(this));
  ...
},

有一個叉子,其中包含上述修改,您可以在此處找到。 您可以通過下載它並在chrome://extensions/下的新標簽中將app文件夾作為未壓縮的擴展名加載來試用。 請享用!


截圖

在此處輸入圖片說明

您始終可以將元素的信息(例如idclassfont-family等)存儲到chrome.storage.local / sync

要處理重新加載,您可以執行一些操作,例如在自定義開發工具標簽中獲取chrome.storage對象和window.location(myElement)

這是我為您解決的問題的解決方法。

想法 :要求內容腳本為被檢查的元素選擇唯一的選擇器,然后將其保存到chrome.storage.local ,這樣您就可以加載選擇器,查找元素並為其運行inspect()

首先是manifest.json文件:

{
  "manifest_version": 2,
  "name": "remember element",
  "version": "1.0.0",
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content-script.js"],
      "run_at": "document_start"
    }
  ],
  "permissions": [
    "storage"
  ],
  "devtools_page": "loader.html"
}

然后,我在Devtools中創建一個新面板。

loader.html

<!doctype html>
<html lang="en">
<body>
  <script src="loader.js"></script>
</body>
</html>

loader.js

chrome.devtools.panels.create('Remember element', null, 'panel.html');

panel.html

<!doctype html>
<html>
<body>

  <button id="save">Save</button>
  <button id="get">Get</button>

  <script src="panel.js"></script>
</body>
</html>

因此,該面板包含兩個按鈕:一個用於保存當前檢查的元素,第二個用於檢查先前保存的元素。

這是我們在panel.js中需要的:

document.addEventListener('DOMContentLoaded', () => {

    // Ask content-script to resolve unique selector and save it in the storage
    document.getElementById('save').addEventListener('click', () => {
        chrome
            .devtools
            .inspectedWindow
            .eval("saveUniqueSelector($0)", {
                useContentScriptContext: true // run the code in the content-script
            });
    });

    document.getElementById('get').addEventListener('click', () => {
        // Getting saved selector
        chrome.storage.local.get('prev_selected', items => {

            // Find the element by selector and run inspection for it
            chrome
                .devtools
                .inspectedWindow
                .eval(`inspect(document.querySelector("${items.prev_selected}"))`);
        });
    });
});

content-script.js

/**
 * Saves unique selector for the given element into chrome.storage
 *
 * The function invokes by panel.js ("chrome.devtools.inspectedWindow.eval")
 * @param el {HTMLElement}
 */
function saveUniqueSelector(el) {
    if (el) {
        const selectorGenerator = new CssSelectorGenerator();
        const selector = selectorGenerator.getSelector(el);
        if (selector) {
            console.log('Saving selector', selector);
            chrome.storage.local.set({prev_selected: selector});
        }
    }
}

有很多庫可用於獲取元素的唯一選擇器。 我在這里使用css-selector-generator

這個例子有一個很大的缺陷:在devtools中選擇元素時,我沒有找到為元素自動保存的方法。 (setInterval除外,但這不是一個好主意)。

擴展DomFlags正是這樣做的。 您可以在元素面板中設置多個標志,並且第一個會在頁面重新加載時自動選擇。

http://domflags.com/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM