使用AJAX加载代码时,添加rel =“ noopener”

时间:2019-03-02 10:56:15

标签: javascript html google-chrome-extension


我为chrome扩展程序创建了一个快速,简单的脚本,可将 <style name="StyledEditText"> <item name="android:imeOptions">actionNone</item> <item name="android:colorControlActivated">@color/colorPrimaryDark</item> <item name="android:textColorPrimary">@color/colorPrimaryDark</item> <item name="android:colorControlHighlight">@color/colorPrimaryDark</item> <item name="android:colorAccent">#FFFFFF</item> </style> 添加到网站上所有带有rel="noopener noreferrer"的链接中。
现在的事情是(例如,在Tumblr上,如果您滚动浏览源),如果在网站上浏览时加载了内容,该脚本显然不会在链接中添加noopener。
现在我想使用MutationObserver,但如果我用脚本更改链接,则MutationObserver显然会识别出更改,并且会出现无限循环。

target="_blank"

任何人都在思考如何检测新链接?

1 个答案:

答案 0 :(得分:1)

rel可以具有多个您不想覆盖的以空格分隔的值(请参见the list)。

使用rel属性的relList DOM接口仅添加缺少的值,因此,当MutationObserver触发时,它将跳过这些链接,而不会陷入无限循环:

// process the current document
onMutation([{
  addedNodes: [document.body],
}]);

// process the future modifications
const mo = new MutationObserver(onMutation);
mo.observe(document, {subtree: true, childList: true});

function onMutation(mutations) {
  var links = [];
  // ES5 loops with vars are still much faster in 2019,
  // which is important for subtree:true, more info: https://stackoverflow.com/a/39332340
  for (var i = 0; i < mutations.length; i++) {
    var addedNodes = mutations[i].addedNodes; 
    for (var j = 0; j < addedNodes.length; j++) {
      var node = addedNodes[j];
      if (node.tagName === 'A' && node.target === '_blank') {
        links.push(node);
      } else if (node.firstElementChild && node.querySelector('a[target*="_blank"]')) {
        links.push(...node.querySelectorAll('a[target*="_blank"]'));
      }
    }
  }

  for (var k = 0; k < links.length; k++) {
    var link = links[k];
    if (!link.relList.contains('noopener')) {
      link.relList.add('noopener');
    }
    if (!link.relList.contains('noreferrer')) {
      link.relList.add('noreferrer');
    }
  }
}

或者您可以在mousedown上附加全局window处理程序,并修改单击的链接:

window.addEventListener('mousedown', e => {
  const link = e.target.closest('a');
  if (link) {
    const {relList} = link;
    if (!relList.contains('noopener')) {
      relList.add('noopener');
    }
    if (!relList.contains('noreferrer')) {
      relList.add('noreferrer');
    }
  }
}, true);