简体   繁体   English

显示灯箱后按需加载JavaScript

[英]Load JavaScript on demand after lightbox is displayed

There is a button on every page of my site. 我网站的每个页面都有一个按钮。 When the button is clicked, a lightbox appears. 单击该按钮时,会出现一个灯箱。 The content of the lightbox is a form that relies on several JavaScript files including Angular. 灯箱的内容是一种依赖于包括Angular在内的多个JavaScript文件的表单。 Those JavaScript files are used only for the form and nowhere else on the site. 这些JavaScript文件仅用于表单,而不是网站上的其他任何地方。

In order to reduce page load time, my goal is to load the JavaScript files only after the user clicks the button. 为了减少页面加载时间,我的目标是仅在用户单击按钮后加载JavaScript文件。

Is there a best practice way of doing this? 这样做有最佳实践方法吗? Some options I can think of are: 我能想到的一些选择是:

  1. The content of the lightbox is an iframe and the sourced html document contains script tags. 灯箱的内容是iframe,源html文档包含脚本标签。
  2. Use the jquery.getscript method (or similar) to load the scripts 使用jquery.getscript方法(或类似方法)加载脚本

Is there a better way? 有没有更好的办法?

By understanding your question, You want to lazy-load your js/css/html . 通过了解你的问题,你想懒惰加载你的js / css / html。 You can achieve this using two plugins 您可以使用两个插件实现此目的

Require.js Require.js

Pros : 优点:

  1. Explicit dependencies between modules, listed in code. 代码中列出的模块之间的显式依赖关系。
  2. Asynchronous module loading. 异步模块加载。
  3. Lazy (on-demand) module loading. 延迟(按需)模块加载。
  4. Support for one of the standard module wrappers (AMD), a lot of community modules implement it, so your modules can depend on them. 支持其中一个标准模块包装器(AMD),许多社区模块实现它,因此您的模块可以依赖它们。

Cons : 缺点:

  1. We can't inject the AngularJS modules on the fly. 我们无法动态注入AngularJS模块。 This loads files only when needed ie RequireJS only loads javascript files but it doesn't register the new angular modules and components in this new code 这仅在需要时加载文件,即RequireJS仅加载javascript文件,但它不会在此新代码中注册新的角度模块和组件

OcLazyLoad OcLazyLoad

Pros : 优点:

  1. OcLazyLoad is used to load the dependency files and also to inject the AngularJS modules on the fly. OcLazyLoad用于加载依赖项文件,也可以动态注入AngularJS模块。
  2. Loading Js and Css files are effortless. 加载Js和Css文件毫不费力。

Cons : 缺点:

  1. We can't maintain the dependency files structure. 我们无法维护依赖文件结构。

So you can use Require.js to load dependencies between modules listed in code and OcLazyLoad to inject Angular module on fly . 因此,您可以使用Require.js加载代码和OcLazyLoad列出的模块之间的依赖关系, OcLazyLoad在运行时注入Angular模块。 And for your question regarding angular itself on fly, I don't think you can do that in this case. 对于你在飞行中angular本身的问题,我认为在这种情况下你不能这样做。

Create script tag and attach script src and append it to head using javascript as below. 创建脚本标记并附加脚本src并使用javascript将其附加到头部,如下所示。

var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', 'test.js');
document.head.appendChild(script);

Another way is to load js file using jquery ajax call like below. 另一种方法是使用jquery ajax调用加载js文件,如下所示。

$.ajax({
    url: "test.js",
    dataType: "script",
    cache: true,
    success: function() {
        //Execute the function which you want...
    }
});

Depending on your project's architecture and whether you are using/want to use a library like require.js could help. 根据您项目的体系结构以及您是否正在使用/想要使用像require.js这样的库可能有所帮助。

You can use it to require in the necessary modules for the lightbox. 您可以使用它来要求灯箱的必要模块。

The benefit of it in contrast to just dynamically loading a bunch of scripts, is that you will be able to manage dependencies between dynamically loading scripts and ensure they execute in a specific order if you need to (now or in the future). 与仅动态加载一堆脚本相比,它的好处是,您将能够管理动态加载脚本之间的依赖关系,并确保它们(如果您需要)(现在或将来)按特定顺序执行。

Another idea could be to call an ajax function on the click of the button that would return an html partial, containing the lightbox scripts that you would then append to the document so the scripts would again load dynamically. 另一个想法可能是在点击按钮时调用ajax函数,该按钮将返回html部分,包含灯箱脚本,然后您将附加到文档,以便脚本再次动态加载。

here is an example of how you achieve, I have implemented something similar on my websites and external JS are loaded only when required 这里有一个如何实现的例子,我在我的网站上实现了类似的东西,外部JS只在需要时加载

<script type='text/javascript'>
$(elem).click(function() {
var d= document;
var id = 'ext-js';
if (d.getElementById(id)) return;
var t = d.createElement('script');
t.type = 'text/javascript';
t.src = '//path to external js';
t.id = id;
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(t);
});
</script>

The code also checks if the script is already loaded so it doesn't try to load with every click, you can easily scale to load multiple scripts, just give each script a different id and copy paste the below section for as many scripts you require. 代码还检查脚本是否已经加载,因此它不会尝试加载每次单击,您可以轻松扩展以加载多个脚本,只需为每个脚本提供不同的ID并复制粘贴以下部分,以获得所需的脚本数量。

var t = d.createElement('script');
t.type = 'text/javascript';
t.src = '//path to external js';
t.id = id;
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(t);

I hope this helps 我希望这有帮助

For the dynamic script loading of the browser,you can use load-script package. 对于浏览器的动态脚本加载,您可以使用load-script包。

  • require('load-script') returns a function of the following interface: function(url[, opts][, cb]) {} require('load-script')返回以下接口的函数:function(url [,opts] [,cb]){}
  • load-script appends a script node to the <head> element in the dom. load-script将脚本节点附加到dom中的<head>元素。

    Example

      var load = require('load-script') load('foo.js', function (err, script) { if (err) { // print useful message } else { console.log(script.src);// Prints 'foo'.js' // use script // note that in IE8 and below loading error wouldn't be reported } }) 

Alternatively you can combine the elements with the DOM 或者,您可以将元素与DOM组合在一起

Example

 <script type="application/javascript">
   function loadJS(file) {
     // DOM: Create the script element
     var jsElement = document.createElement("script");
     // set the type attribute
     jsElement.type = "application/javascript";
     // make the script element load file
     jsElement.src = file;
     // finally insert the element to the body element in order to load the script
     document.body.appendChild(jsElement);
   }
 </script>

   <button onclick="loadJS('jsFile1.js');">Load jsFile1.js</button>
   <button onclick="loadJS('jsFile2.js');">Load jsFile2.js</button>

Option 2 (dynamically loading scripts) is a good way to go - you probably just need to bootstrap angularjs correctly once it's been loaded. 选项2(动态加载脚本)是一个很好的方法 - 你可能只需要在加载后正确引导angularjs A quick demo: 快速演示:

 (function() { "use strict"; var angularLoaded = false; window.lazyLoadAngular = function() { if (angularLoaded) { return; } angularLoaded = true; var angularScript = document.createElement("script"); angularScript.src = "//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"; document.body.appendChild(angularScript); angularScript.onload = function() { var angular = window.angular, angularContent = document.querySelector('.angularContent'); // reveal angular content angularContent.style.display = "block"; // in practice, you're probably dynamically loading your angular app scripts as well... but here we'll just create it once angular is available createAngularApp(); // bootstrap angular on the content angular.bootstrap(angularContent, ["myApp"]); }; }; function createAngularApp() { var angular = window.angular; angular.module("myApp", []) .controller("MyCtrl", ["$scope", MyCtrl]); function MyCtrl($scope) { $scope.isAngularWorking = "Yes it is!"; } } })(); 
 .angularContent { display: none; } 
 <button onclick="lazyLoadAngular()">Lazy load Angular</button> <div class="angularContent"> <div ng-controller="MyCtrl"> Angular is working: {{isAngularWorking}} </div> </div> 

你可以使用SystemJsUniversal动态模块加载器 - 在浏览器和 NodeJS中 加载ES6模块,AMD,CommonJS和全局脚本 ,我认为是非常强大的引擎。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM