【问题标题】:Getting scripts to load only after DOM 100% ready in Meteor?只有在 Meteor 中的 DOM 100% 准备好后才能加载脚本?
【发布时间】:2015-08-20 02:23:15
【问题描述】:

我使用的是 Bootstrap 模板,它们的 HTML 和 CSS / JS 加载顺序是这样的:

<!DOCTYPE html>
<!--[if IE 8]>          <html class="ie ie8"> <![endif]-->
<!--[if IE 9]>          <html class="ie ie9"> <![endif]-->
<!--[if gt IE 9]><!-->  <html> <!--<![endif]-->
    <head>
        <meta charset="utf-8" />
        <title>Atropos - Responsive Multipurpose</title>
        <meta name="keywords" content="HTML5,CSS3,Template" />
        <meta name="description" content="" />
        <meta name="Author" content="Dorin Grigoras [www.stepofweb.com]" />

        <!-- mobile settings -->
        <meta name="viewport" content="width=device-width, maximum-scale=1, initial-scale=1, user-scalable=0" />

        <!-- WEB FONTS -->
        <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,700,800" rel="stylesheet" type="text/css" />

        <!-- CORE CSS -->
        <link href="assets/plugins/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
        <link href="assets/css/font-awesome.css" rel="stylesheet" type="text/css" />
        <link href="assets/plugins/owl-carousel/owl.carousel.css" rel="stylesheet" type="text/css" />
        <link href="assets/plugins/owl-carousel/owl.theme.css" rel="stylesheet" type="text/css" />
        <link href="assets/plugins/owl-carousel/owl.transitions.css" rel="stylesheet" type="text/css" />
        <link href="assets/plugins/magnific-popup/magnific-popup.css" rel="stylesheet" type="text/css" />
        <link href="assets/css/animate.css" rel="stylesheet" type="text/css" />
        <link href="assets/css/superslides.css" rel="stylesheet" type="text/css" />

        <!-- REVOLUTION SLIDER -->
        <link href="assets/plugins/revolution-slider/css/settings.css" rel="stylesheet" type="text/css" />

        <!-- THEME CSS -->
        <link href="assets/css/essentials.css" rel="stylesheet" type="text/css" />
        <link href="assets/css/layout.css" rel="stylesheet" type="text/css" />
        <link href="assets/css/layout-responsive.css" rel="stylesheet" type="text/css" />
        <link href="assets/css/color_scheme/orange.css" rel="stylesheet" type="text/css" /><!-- orange: default style -->
        <!--<link id="css_dark_skin" href="assets/css/layout-dark.css" rel="stylesheet" type="text/css" />--><!-- DARK SKIN -->

        <!-- styleswitcher - demo only -->
        <link href="assets/css/color_scheme/orange.css" rel="alternate stylesheet" type="text/css" title="orange" />
        <link href="assets/css/color_scheme/red.css" rel="alternate stylesheet" type="text/css" title="red" />
        <link href="assets/css/color_scheme/pink.css" rel="alternate stylesheet" type="text/css" title="pink" />
        <link href="assets/css/color_scheme/yellow.css" rel="alternate stylesheet" type="text/css" title="yellow" />
        <link href="assets/css/color_scheme/darkgreen.css" rel="alternate stylesheet" type="text/css" title="darkgreen" />
        <link href="assets/css/color_scheme/green.css" rel="alternate stylesheet" type="text/css" title="green" />
        <link href="assets/css/color_scheme/darkblue.css" rel="alternate stylesheet" type="text/css" title="darkblue" />
        <link href="assets/css/color_scheme/blue.css" rel="alternate stylesheet" type="text/css" title="blue" />
        <link href="assets/css/color_scheme/brown.css" rel="alternate stylesheet" type="text/css" title="brown" />
        <link href="assets/css/color_scheme/lightgrey.css" rel="alternate stylesheet" type="text/css" title="lightgrey" />
        <!-- /styleswitcher - demo only -->



        <!-- STYLESWITCHER - REMOVE ON PRODUCTION/DEVELOPMENT -->
        <link href="assets/plugins/styleswitcher/styleswitcher.css" rel="stylesheet" type="text/css" />     

        <!-- Morenizr -->
        <script type="text/javascript" src="assets/plugins/modernizr.min.js"></script>
    </head>
    <body><!-- Available classes for body: boxed , pattern1...pattern10 . Background Image - example add: data-background="assets/images/boxed_background/1.jpg"  -->

-- 这里有很多 HTML --

    <!-- JAVASCRIPT FILES -->
    <script type="text/javascript" src="assets/plugins/jquery-2.0.3.min.js"></script>
    <script type="text/javascript" src="assets/plugins/jquery.easing.1.3.js"></script>
    <script type="text/javascript" src="assets/plugins/jquery.cookie.js"></script>
    <script type="text/javascript" src="assets/plugins/jquery.appear.js"></script>
    <script type="text/javascript" src="assets/plugins/jquery.isotope.js"></script>
    <script type="text/javascript" src="assets/plugins/masonry.js"></script>

    <script type="text/javascript" src="assets/plugins/bootstrap/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="assets/plugins/magnific-popup/jquery.magnific-popup.min.js"></script>
    <script type="text/javascript" src="assets/plugins/owl-carousel/owl.carousel.min.js"></script>
    <script type="text/javascript" src="assets/plugins/stellar/jquery.stellar.min.js"></script>
    <script type="text/javascript" src="assets/plugins/knob/js/jquery.knob.js"></script>
    <script type="text/javascript" src="assets/plugins/jquery.backstretch.min.js"></script>
    <script type="text/javascript" src="assets/plugins/superslides/dist/jquery.superslides.min.js"></script>
    <script type="text/javascript" src="assets/plugins/styleswitcher/styleswitcher.js"></script><!-- STYLESWITCHER - REMOVE ON PRODUCTION/DEVELOPMENT -->
    <script type="text/javascript" src="assets/plugins/mediaelement/build/mediaelement-and-player.min.js"></script>

    <!-- REVOLUTION SLIDER -->
    <script type="text/javascript" src="assets/plugins/revolution-slider/js/jquery.themepunch.plugins.min.js"></script>
    <script type="text/javascript" src="assets/plugins/revolution-slider/js/jquery.themepunch.revolution.min.js"></script>
    <script type="text/javascript" src="assets/js/slider_revolution.js"></script>


    <script type="text/javascript" src="assets/js/scripts.js"></script>


    <!-- Google Analytics: Change UA-XXXXX-X to be your site's ID. Go to http://www.google.com/analytics/ for more information. -->
    <!--<script>
        (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

        ga('create', 'UA-XXXXX-X', 'domainname.com');
        ga('send', 'pageview');
    </script>
    -->

</body>

只有在浏览器中的 DOM 100% 准备好之后,才需要在底部加载相当多的 JS。

不幸的是,我很难把握好时机 - 我的页面仍然无法像演示那样运行 - 滑块没有显示,视差不起作用,而且我确定很多事情也不起作用,我没有注意到。我确信这正在发生,因为当 Meteor 加载 JS(通常全部加载在底部)时,一些 DOM 节点还不存在。

这是我尝试过的:

注意:我还想将很多这些 JS 文件直接放入 client/javascripts,以便在生产环境中利用 Meteor 的自动缩小和捆绑功能

1 .我认为在布局模板渲染之后是 DOM 应该准备好的时候,所以我打算在布局渲染之后将脚本标签附加到正文,但这不起作用。

Template.layout.onRendered(function() {

    console.log('layout rendered');

    var appendToHead = function(array){
        for (index in array){
            $('head').append(array[index]);
        };
    };

    var array = [
      // an array of all the script tags
      '<script type="text/javascript" src="assets/plugins/jquery-2.0.3.min.js"></script>',
      '<script type="text/javascript" src="assets/plugins/jquery.easing.1.3.js"></script>'
      // etc...
    ];

    appendToHead(array);

});
  1. 我已尝试将此函数包装在 Tracker.afterFlush() 中,但这也不起作用。

  2. 我已尝试将此函数放入 main.js,但这不起作用。

  3. 我已尝试将其包装在 Meteor.startup() 中,但不起作用。

  4. 我什至尝试将其包装在 $('document').ready() 中,但没有成功。

  5. 我要冒昧地说,即使把所有东西都放在自己的包中也行不通,因为包只能根据它对其他 JS 文件的依赖关系来控制包的加载顺序,但是没有能力根据 DOM 状态控制加载顺序,对吧?

顺便说一句,我将控制台日志放在每次尝试旁边,这是它们被触发的顺序。

code inside Tracker.afterFlush has been fired
code inside main.js has been fired
code inside jQuery document.ready() has been fired
code inside layout.onRendered has been fired

部分困难在于 Meteor 的分散模板性质。一段 JS 代码(比如说幻灯片)需要一个 DOM 元素存在才能运行。在渲染布局时加载该代码是没有意义的,因为布局只是布局并且没有 DOM 元素。幻灯片需要的 DOM 元素包含在 {{&gt; intro}}{{&gt; photos}}{{&gt; videos}} 模板中。

但是编写代码来为这三个单独的模板分别加载幻灯片 JS 三次也很乏味...

如果您使用了 8 个不同的 3rd-party JS 脚本怎么办?一个模板使用四个,另一个使用八个,另一个使用一个,另一个使用六个。必须一遍又一遍地在每个单独模板的 onRendered 回调中定义要加载的脚本,这将是一件非常痛苦的事情。

【问题讨论】:

    标签: meteor


    【解决方案1】:

    您可以使用主模板的 render() 方法按给定顺序加载所需的 JS 脚本。假设您的主模板(或顶级模板)被命名为 appLayout 然后您可以定义如下 render() 方法。

    将所有 JS 文件放在流星应用的 public\js 文件夹中。

    Template.appLayout.rendered = function() {
      if (!window.allScriptsLoaded) {
        var scripts = [
          // list of JS files to be loaded.
          'js/libs/jquery-2.1.1.min.js',
          'js/libs/jquery-ui-1.10.3.min.js',
          'js/plugin/jquery-touch/jquery.ui.touch-punch.min.js',
          'js/bootstrap/bootstrap.min.js'
        ];
    
        function loadNext() {
          var src = scripts.shift();
          if (typeof src === 'undefined')
            return;
    
          var s = document.createElement("script");
    
          s.setAttribute('src', src);
          if (s.addEventListener) {
            s.addEventListener("load", loadNext, false);
          } else if (s.readyState) {
            s.onreadystatechange = loadNext;
          }
          document.body.appendChild(s);
        };
    
        loadNext();
        window.allScriptsLoaded = true;
      }
    }

    这样您就可以精确控制文件的加载顺序。

    【讨论】:

    • 我想继续将 JS 文件放入 client 文件夹中,以利用 Meteor 在生产中内置的缩小和捆绑能力。
    • 如果你把东西放在客户端,你会失去对流星的控制,然后流星会缩小和捆绑你的 JS 并自动加载它。然后你就无法控制它了。
    • 我想没有办法在利用 Meteor 的缩小和捆绑的同时仍然控制与 DOM / 模板相关的加载顺序?
    • 不完全是,您可以将内容保存在client 文件夹中,并且仍然可以按照您的方式进行排序,但是您需要处理很多事情(meteor loading priority)并更改文件名,添加/删除文件及其在文件夹结构中的位置可能会更改顺序并为您搞砸事情。更简洁的方法是将内容保存在public 中并根据需要加载,如上面的代码所示。
    • 我明白了。你会碰巧知道一个气氛包,它也可以捆绑+缩小 /public 中的东西吗?我这里和那里有很多小文件,我想将所有内容合并到尽可能少的缩小文件中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 2020-01-14
    • 2014-07-19
    • 2011-05-06
    • 2019-01-23
    相关资源
    最近更新 更多