首页 > 解决方案 > 在多个用户脚本之间共享库

问题描述

我有一个由多个用户脚本使用的库脚本。这个库做了一些繁重的工作(即 CPU 密集型操作),所以我希望只运行该库的 1 个实例。

这是一个最小的例子:

lib.js

let callbacks = [];

document.addEventListener('click', function(event){
    // pretend that something expensive happens in here

    for (callback of callbacks)
        callback();
});

script1.user.js

// @match foo.bar
// @require lib.js

callbacks.push(function(){
    console.log('Script 1: '+callbacks.length+' callback(s) registered');
});

script2.user.js

// @match foo.bar
// @require lib.js

callbacks.push(function(){
    console.log('Script 2: '+callbacks.length+' callback(s) registered');
});

使用此设置,单击鼠标后的输出将是:

Script 1: 1 callback(s) registered
Script 2: 1 callback(s) registered

因为每个用户脚本都有自己的库实例。我该怎么做才能让它们使用相同的库实例,所以我得到这样的输出:

Script 1: 2 callback(s) registered
Script 2: 2 callback(s) registered

笔记:

标签: javascriptrequireuserscripts

解决方案


最简单的方法是让库脚本在窗口尚不存在时将其自身分配给窗口,标准单例样式。

lib.js

const win = typeof unsafeWindow === 'undefined' ? window : unsafeWindow;

if (!win.myLib) {
  win.myLib = {
    callbacks: []
    // assign other properties/methods as needed
  };

  document.addEventListener('click', function(){
    for (const callback of win.myLib.callbacks)
      callback();
  });
}

script1.user.js

// @require lib.js
const { myLib } = window;
myLibrary.callbacks.push(function(){
  console.log('Script 1: ' + myLib.callbacks.length + ' callback(s) registered');
});

script2.user.js

// @require lib.js
const { myLib } = window;
myLibrary.callbacks.push(function(){
  console.log('Script 2: ' + myLib.callbacks.length + ' callback(s) registered');
});

根据用户脚本管理器,您可能不得不unsafeWindow在某些情况下使用。


推荐阅读