最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Load script file on demand with vanilla js - Stack Overflow

programmeradmin0浏览0评论

I use an accordion or tabs. When clicking on a tab, I want to display a map or something that require a big javascript file to load.

To not load the big javascript when it is not needed, I want to load it only when the tab is clicked.

How can I do that? I've created a good starting point with accordion and a click event.

  • I use vanilla js (pure javascript - no jQuery)
  • I use it on a webpage (not nodejs)
  • I'm fine if it works with modern browsers (IE not needed)

window.addEventListener('DOMContentLoaded', () => {
  document.querySelector('[data-trigger]').addEventListener('click', () => {
    console.log('Load script from file');
    // CDN example - .12.0/mapbox-gl.js
  });
});
ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

label {
  display: flex;
  align-items: center;
}

label:before {
  content: '';
  background-image: url("data:image/svg+xml,%3Csvg xmlns='' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M13.172 12l-4.95-4.95 1.414-1.414L16 12l-6.364 6.364-1.414-1.414z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  width: 24px;
  height: 24px;
}

input[type=checkbox] {
  display: none;
}

input[type=checkbox]:checked ~ h2 label:before {
  transform: rotate(90deg);
}

p {
  display: none;
}

input[type=checkbox]:checked ~ h2 ~ p {
  display: block;
}
<ul>
  <li>
    <input type="checkbox" id="faq-1">
    <h2 data-trigger>
      <label for="faq-1">Click to load map</label>
    </h2>
    <p>Gummies marzipan croissant chupa chups.</p>
  </li>

  <li>
    <input type="checkbox" id="faq-2">
    <h2>
      <label for="faq-2">Something else</label>
    </h2>
    <p>Cookie bear claw carrot cake croissant.</p>
  </li>
</ul>

I use an accordion or tabs. When clicking on a tab, I want to display a map or something that require a big javascript file to load.

To not load the big javascript when it is not needed, I want to load it only when the tab is clicked.

How can I do that? I've created a good starting point with accordion and a click event.

  • I use vanilla js (pure javascript - no jQuery)
  • I use it on a webpage (not nodejs)
  • I'm fine if it works with modern browsers (IE not needed)

window.addEventListener('DOMContentLoaded', () => {
  document.querySelector('[data-trigger]').addEventListener('click', () => {
    console.log('Load script from file');
    // CDN example - https://cdnjs.cloudflare./ajax/libs/mapbox-gl/1.12.0/mapbox-gl.js
  });
});
ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

label {
  display: flex;
  align-items: center;
}

label:before {
  content: '';
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M13.172 12l-4.95-4.95 1.414-1.414L16 12l-6.364 6.364-1.414-1.414z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  width: 24px;
  height: 24px;
}

input[type=checkbox] {
  display: none;
}

input[type=checkbox]:checked ~ h2 label:before {
  transform: rotate(90deg);
}

p {
  display: none;
}

input[type=checkbox]:checked ~ h2 ~ p {
  display: block;
}
<ul>
  <li>
    <input type="checkbox" id="faq-1">
    <h2 data-trigger>
      <label for="faq-1">Click to load map</label>
    </h2>
    <p>Gummies marzipan croissant chupa chups.</p>
  </li>

  <li>
    <input type="checkbox" id="faq-2">
    <h2>
      <label for="faq-2">Something else</label>
    </h2>
    <p>Cookie bear claw carrot cake croissant.</p>
  </li>
</ul>

Share Improve this question asked Oct 8, 2020 at 5:47 Jens TörnellJens Törnell 24.8k46 gold badges130 silver badges223 bronze badges 1
  • 1 try document.write? or let myScript = document.createElement("script"); myScript.setAttribute("src", "example./foo.js"); document.body.appendChild(myScript); – astigmatik Commented Oct 8, 2020 at 5:57
Add a ment  | 

2 Answers 2

Reset to default 4

As you're fortable with only supporting modern browsers, you could use the dynamic import() function to load the file:

window.addEventListener('DOMContentLoaded', () => {
  document.querySelector('[data-trigger]').addEventListener('click', async() => {
    const module = await import('https://cdnjs.cloudflare./ajax/libs/mapbox-gl/1.12.0/mapbox-gl.js');
    console.log(`module is loaded: ${Object.keys(mapboxgl)}`);
  });
});
ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

label {
  display: flex;
  align-items: center;
}

label:before {
  content: '';
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M13.172 12l-4.95-4.95 1.414-1.414L16 12l-6.364 6.364-1.414-1.414z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  width: 24px;
  height: 24px;
}

input[type=checkbox] {
  display: none;
}

input[type=checkbox]:checked~h2 label:before {
  transform: rotate(90deg);
}

p {
  display: none;
}

input[type=checkbox]:checked~h2~p {
  display: block;
}
<ul>
  <li>
    <input type="checkbox" id="faq-1">
    <h2 data-trigger>
      <label for="faq-1">Click to load map</label>
    </h2>
    <p>Gummies marzipan croissant chupa chups.</p>
  </li>

  <li>
    <input type="checkbox" id="faq-2">
    <h2>
      <label for="faq-2">Something else</label>
    </h2>
    <p>Cookie bear claw carrot cake croissant.</p>
  </li>
</ul>

import() returns a promise which is resolved on successful fetch, and resolves immediately on subsequent calls (in my testing), so you wouldn't have to deal with that specifically.

For your specific mapbox-gl script, the value returned won't be useful, as the script isn't written as an ES6 module, but the side-effects of the script running will be in place (in this case, the mapboxgl variable being assigned onto globalThis). In scenarios where the loaded script is a module (using export correctly), you can use the resolved value directly to avoid polluting the global namespace.

You could dynamically create a script tag and add it to the document whenever the button is pressed. This will trigger the script to immediately be loaded. With the onload callback you can run your code, like creating a map, the moment the script has actually loaded.

Do add { once: true } as the third parameter for addEventListener as it will ensure that the trigger can only be clicked once and won't be able to append the script more than once.

function createMap() {
  const map = new mapboxgl.Map({
    ...
  });
}

window.addEventListener('DOMContentLoaded', () => {
  document.querySelector('[data-trigger]').addEventListener('click', () => {
    console.log('Load script from file');
    
    const script = document.createElement('script');
    script.id = 'mapboxgljs';
    script.src = 'https://cdnjs.cloudflare./ajax/libs/mapbox-gl/1.12.0/mapbox-gl.js'
    script.async = true;
    script.onload = function() {
      console.log('script loaded, you can use it now.');
      createMap();
    }
    document.body.append(script);
  }, { once: true }); // Make sure that the button can only be pressed once.
});
发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>