单击事件仅加载一次脚本

loading script only once on click event

我一起破解了 vanilla javascript 以在点击事件时加载外部脚本。

var searchLabel = document.getElementById('search-toggle-label');
searchLabel.onclick = function(){
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = "wp-content/themes/2016/js/cse.js."; 
    document.getElementsByTagName("head")[0].appendChild(script);
    return false;
}

但每次点击事件时它都会加载相同的脚本。

所以我加入了一个 if 语句来检查值和类型。 "==="

var searchLabel = document.getElementById('search-toggle-label');
if (typeof searchLabel === 'undefined') {
    searchLabel.onclick = function() {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = "wp-content/themes/2016/js/cse.js."; 
        document.getElementsByTagName("head")[0].appendChild(script);
        return false;
    }
}
else {
    alert('loaded already');
}

显然,这是错误的,因为我在页面加载和点击事件时收到警告,脚本没有加载。

我很难过。我知道使用 jQuery 有一个简单的解决方案,但我正在尝试真正学习编写 javascript.

任何帮助将不胜感激。

如果 DOM 中存在脚本,则向 return true/false 添加一个函数。这是一个:

function isScriptLoaded(src) {
  return !!Array.prototype.filter.call(document.getElementsByTagName('script'), function(node) {
    return node.src === src;
  });
}

然后用它来测试脚本是否已经插入 DOM。

也许可以尝试在函数定义之前设置一个标志。这样你就可以在函数开始时检查标志并忽略其余部分。你也有一个很好的例子,我在互联网上找到了。查一下这个 solution.

事件侦听器触发后将其移除:

var searchLabel = document.getElementById('search-toggle-label');
searchLabel.addEventListener('click', loadScript('wp-content/themes/2016/js/cse.js'), false);

function loadScript(src){
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = src; 
    document.head.append(script);
    return searchLabel.removeEventListener('click', loadScript, false);
}

使用它来同步加载脚本(并且只加载一次):

const isScriptLoaded = (src)=>{
  const scripts = Array.from(document.getElementsByTagName('script')) || []
  return scripts.filter((node) => node.src && node.src.indexOf(src)>-1).length>0
}

const loadScript = (src, once=true)=>{
  if (once && isScriptLoaded(src)) return

  return new Promise((resolve)=>{
    const node = document.createElement('script')
    node.setAttribute('src', src)
    node.onload = ()=>{ 
      setTimeout(()=>{ resolve() }, 0)
    }
    document.getElementsByTagName('head')[0].appendChild(node)
  })
}

然后,在你的 vue 组件中:

  ...

  async mounted () {
    await loadScript('/js/globe.min.js') // wait for the script to be loaded
    // this.scriptIsReadyLetsDoSomethingWithIt()
    
    // Will do nothing if you call loadScript multiple times (as the script is already loaded)
    // await loadScript('/js/globe.min.js')
    
  },
  ...