【问题标题】:Dynamically loading a script changes its behaviour动态加载脚本会改变其行为
【发布时间】:2012-12-16 02:54:13
【问题描述】:

我希望 paperjs 在按下按钮以打开动画后加载,但如果在页面加载后加载纸张,paperscript 似乎不起作用。

如果您注释掉setTimeout 并取消注释直接$.getScript - paperjs 将触发alert('hi')。没看懂。

<html>
    <head>
        <script src="http://code.jquery.com/jquery-latest.js"></script>
        <script>
            $(document).ready(function () {
                var paperUrl = 'http://cdnjs.cloudflare.com/ajax/libs/paper.js/0.22/paper.js';
                $("#jq").text("jQuery is now loaded.")
                var lateLoad = function() {
                    $.getScript(paperUrl, function() {
                        $("#pp").text("Paperjs is now loaded.");
                    });
                };
                //setTimeout(lateLoad, 100);
                $.getScript(paperUrl, function() {
                    $("#pp").text("Paperjs is now loaded.");
                });
            });
        </script>
    </head>
    <body>
        <script type="text/paperscript" canvas="myCanvas">
            $('body').css({"background-color": "#999"});
            alert('hi!');
        </script>
        <p id="jq">jQuery NOT loaded yet.</p>
        <p id="pp">Paperjs NOT loaded yet.</p>
    </body>
</html>

我在 Windows 7 x64 上使用 Chrome 23.0.1271.97 m。有人知道这里发生了什么吗?

【问题讨论】:

    标签: javascript javascript-framework jquery-events paperjs


    【解决方案1】:

    我想我也想出了一个解决方法 - paper.PaperScript.load() 或详细说明:

    <html>
        <head>
            <script src="http://code.jquery.com/jquery-latest.js"></script>
            <script>
                $(document).ready(function () {
                    $("#jq").text("jQuery is now loaded.")
                    var paperUrl = 'http://cdnjs.cloudflare.com/ajax/libs/paper.js/0.22/paper.js';
                    var lateLoad = function() {
                        $.getScript(paper_url, function() { 
                            $("#pp").text("Paperjs is now loaded.");
                            paper.PaperScript.load(); // <-- The fix!
                        });
                    };
                    setTimeout(lateLoad, 1000);
                    //$.getScript(paperUrl, function() {
                    //    $("#pp").text("Paperjs is now loaded.");
                    //});
                });
            </script>
        </head>
        <body>
            <script type="text/paperscript" canvas="myCanvas">
                $('body').css({"background-color": "#999"});
                alert('hi!');
            </script>
            <p id="jq">jQuery NOT loaded yet.</p>
            <p id="pp">Paperjs NOT loaded yet.</p>
        </body>
    </html>
    

    这会导致 paperscript 扫描所有的 paperscript。我在https://github.com/paperjs/paper.js/blob/master/src/core/PaperScript.js#L270 在 github 存储库中搜索“paperscript”时找到了它。虽然它仍然没有解释为什么动态加载时纸张不会自己执行 load()。

    编辑 - 我明白出了什么问题。它与https://github.com/jquery/jquery/blob/master/src/core.js#L768 相关,因为paperjs 不检查窗口加载事件是否已经触发,即document.readyState === "complete"。我向paperjs https://github.com/paperjs/paper.js/pull/156提交了一个拉取请求

    【讨论】:

    • 最好在 getScript 中添加一些换行符,尤其是在 paper.PaperScript.load(); 之前。因为我必须在页面上搜索“.load”才能了解你做了什么以及在哪里;)
    • 你说得对,我也花了很长时间才弄明白。我希望现在修复它。我最近才学习了用于回调缩进的 node.js 约定。多么美丽。
    【解决方案2】:

    将您的 paperscript 代码移动到外部文件(即 pstest.js)中并将您的 lateLoad 修改为:

    var lateLoad = function() {
        $.getScript('http://cdnjs.cloudflare.com/ajax/libs/paper.js/0.22/paper.js',
        function() {
          $("#pp").text("Paperjs is now loaded.");
          $.getScript("pstest.js");
        } )
    }
    

    【讨论】:

      【解决方案3】:

      我认为通过require.js 加载它更容易。您所需要的只是一个require.config 对象,例如定义在main.js:

      requirejs.config({
          paths : {   
              'jquery' : "path/to/jquery"
              'paper' : "path/to/paper"
          },
          shim: {
              'jquery' : {
                  exports: 'jQuery'
              },
              'paper' : {
                  exports: 'paper'
              }
          }
      });
      

      您需要通过data-main 属性加载带有上述配置的require.js:

      <script data-main="scripts/main.js" src="scripts/require.js"></script>
      

      然后你定义一个模块(例如'paperStuff'),你的论文逻辑将是:

      define(['jquery', 'paper'], function($, paper) {
         // do some cool stuff
      });
      

      当您想加载 paperStuff 时,您只需这样做

      var paperStuff = require('paperStuff');
      ...
      

      【讨论】:

      • 相当复杂的脚本加载解决方案,jquery 自己做的很好。我不确定这是否能解决任何问题,或者我是否想要另一个 javascript 依赖项...
      • 您的带有 alert('hi') 的脚本将始终显示,因为它在全局范围内。您需要在 $.getScript() 范围内加载它。你不能将它存储在一个单独的文件中并在 paperjs getScript 加载中使用第二个 getScript() 调用来加载它吗?
      • 你注意到type="text/paperscript"了吗?因为这会导致浏览器跳过它,只有 paperjs 执行它。
      • 嗯,好的。没关系。我不使用paperjs。也许如果你加载 paperJs,它会在执行加载的回调之前先评估页面?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 1970-01-01
      • 2014-03-10
      • 2016-03-30
      • 2011-12-07
      • 1970-01-01
      相关资源
      最近更新 更多