【问题标题】:How to deal with multiple scripts in a single page web application如何在单页 Web 应用程序中处理多个脚本
【发布时间】:2012-10-09 01:09:10
【问题描述】:

我是 Web 开发的新手,我开始了一个应用程序,其中我有一个带有菜单的 index.php 和一个名为 #content 的 div,我使用 load() 将所有不同的页面加载到 div #content 中;我需要加载相应的 java 脚本文件以及正在加载到 div #content 的文件。

问题:在加载到 div 的 HTML 中,我有一些相似的类名和 id,所以当我单击任何菜单项并在那里执行一些操作并转到另一个菜单项并执行相同的操作时,我得到上一个菜单项的脚本正在执行中!

有没有更好的方法在单击菜单项时将脚本加载到 div 中,并在单击另一个菜单项时删除以前的脚本并从当前单击的菜单项中加载新的脚本?

我用来加载 div #content 的脚本:

$('.nav-button').on('click', function(e){
e.preventDefault();
$('#content').load('../scripts/loader.php');
$('#content').load($(this).attr('href'));
});

sample1.php 页面我加载到 menu-item1 上的 div 点击:

<div id='datagrid'>
<input></input>
<input></input>
<input></input>
</div>
<script type='text/javascript' src='scripts/menu-item1/data_script.js'></script>

sample2.php 页面我加载到 menu-item2 上的 div 点击:

<div id='datagrid'>
<input></input>
<input></input>
<input></input>
</div>
<script type='text/javascript' src='scripts/menu-item2/data_script.js'></script>

【问题讨论】:

  • data_script.js:名称相同,但如果内容相同,为什么还要麻烦加载和卸载它们。只需使用 index.php 加载它们并使用。
  • 内容绝对不相同。正如我提到的,不同的菜单项(类别)有不同的脚本。

标签: php javascript jquery


【解决方案1】:

另一种加载脚本的方式:

var script = document.createElement("script");
script.type = "text/javascript";
script.src = src;
script.onload = callback_function;

document.getElementsById("#scriptContainer")[0].appendChild(script);

关于删除现有脚本:

尝试将您的脚本加载到某个容器中,当您想要替换它们时,只需清除容器内容并加载您的新脚本。

您也可以尝试使用 requirejs 进行延迟加载。 Example here

【讨论】:

    【解决方案2】:

    一旦加载并执行了脚本,除非您自己整理代码,否则即使您删除/删除了原始脚本标记,您仍然会保留该代码的残余。以下几点应该会有所帮助:

    1. 每当您在 js 中创建/导入结构时,请确保您已编写了取消导入/销毁功能。
    2. 不要依赖通过.innerHTML$().html() 插入的脚本标签 - 较旧的浏览器不尊重它们,这可能会导致意外结果 - 即脚本标签被忽略,或者在较旧的 Internet Explorer 的情况下,试图从错误的地方加载。
    3. 而是按照 thedev 的建议进行操作,并以编程方式构建您的脚本标签。
    4. 如果您想让每个 ajax 脚本返回其关联的脚本标签,那么显然 #3 会很棘手。
    5. 因此,不是在您的 ajax 请求中返回纯 HTML,而是返回一个 JSON 对象,其中包含 HTML 和需要加载的脚本路径列表。
    6. 如果您确保每个加载的脚本都通过一个特别命名的对象公开其所有方法,那么您可以在下次加载下一个脚本时删除该对象。

    下面是说明性代码,有更复杂的(更好的)方法来处理这个(即避免在窗口上存储对象),加上下面的代码可以在许多地方都需要改进 - 它应该只会让您了解您可以做什么以及如何思考它。

    还应注意,在全局window 对象上存储对象时,应使用比onetwothree 更多的唯一名称;)

    标记:

    <ul class="menu">
      <li><a href="one.html" data-namespace="one">One Link</a></li>
      <li><a href="two.html" data-namespace="two">Two Link</a></li>
      <li><a href="three.html" data-namespace="three">Three Link</a></li>
    </ul>
    <div id="content">
      ...
    </div>
    

    javascript:

    /// create a wrapping scope so that our variables can be local
    /// to our internal code, but not mess around with the global space.
    (function(){
    
      /// create a remembered lastID var that can store what item was loaded
      var lastID;
    
      /// an addScripts function that takes a string namespace (can be anything
      /// as long as it obeys usual javascript variable naming rules), and an
      /// array of script URIs.
      var addScripts = function(namespace, scripts){
        var s,i;
        for( i=0; i<scripts.length; i++ ){
          s = $('<script />')
                /// attach our src attribute with the right script path
                .attr('src', scripts[i])
                /// add our namespace as a class to help find script tag later
                .addClass(namespace); 
          /// add to the head of the document
          $('head').append(s);
        }
      }
    
      /// removeScripts works based on using the namespace we passed
      /// when adding scripts as a classname to find the script tags.
      /// remember removing the tags doesn't remove the executed code.
      var removeScripts = function(namespace){
        /// in order to tidy our code we should include a function
        /// to tidy up.
        if ( window[namespace] && window[namespace].tidyup ) {
          window[namespace].tidyup();
        }
        /// remove the tag to keep the markup neat
        $('script.'+namespace).remove();
      }
    
      /// a typical click handler applied to the a tags
      $('.menu a').click(function(){
    
        /// if we have a lastID remove what was before.
        if ( lastID ) {
          removeScripts(lastID);
        }
    
        /// get our useful info from the link
        var target = $('#content');
        var url = $(this).attr('href');
        /// grab out our "namespace" this will be used to tie the scripts
        /// together with the collection object in the loaded javascript.
        var namespace = $(this).attr('data-namespace');
    
        /// trigger an ajax request that fetches our json data
        /// from the server.
        $.ajax('loader.php',{dataType:'json',data:{url:url}})
          .done(function(data){
            /// once we have that data, add the html to the page
            target.html( data.html );
            /// and then add the scripts
            addScripts( id, data.scripts || [] );
          });
    
        /// store the last id so we know what to remove next time
        lastID = id;
    
      });
    
    })();
    

    loader.php:

    <?php
    
      /// create a library of what scripts belong to what page
      $scripts = array(
        'one.html' => array('scripts/js/one.js'),
        'two.html' => array('scripts/js/two.js'),
        'three.html' => array('scripts/js/three.js'),
      );
    
      /// because `$_GET[url]` can be affected by outside influence
      /// make sure you check it's value before using it.
      switch( ($file = basename($_GET['url'])) ){
        case 'one.html':
        case 'two.html':
        case 'three.html':
          $json = (object) null;
          if ( file_exists($file) ) {
            $json->html = file_get_contents($file);
          }
          if ( isset($scripts[$file]) ) {
            $json->scripts = $scripts[$file];
          }
          header('content-type: application/json');
          /// json_encode should handle escaping all your html correctly
          /// so that it reaches your javascript in one correct piece.
          echo json_encode($json);
        break;
      }
    
    ?>
    

    json(由上面的php返回):

    {
      "html": "<div class=\"random-content\">This can be anything</div>",
      "scripts": ["scripts/js/one.js"]
    }
    

    示例 js 包括 - 即 (one.js)

    /// create our collection object named with the same namespace that
    /// appears in the data-namespace attribute in the markup.
    window.one = {};
    
    window.one.someMethodThatMightBeUsedByLoadedContent = function(){
      /// this function has been kept specifically as part of the 'one'
      /// object because it needs to be globally accessible by the html
      /// that has been injected into the page. by keeping it as part
      /// of a named object, removing it is rather simple. (see tidyup).
    }
    
    window.one.tidyup = function(){
      /// this is the most simplistic way of tidying up a property. Depending
      /// on the complexity of your javascript there are other things you should
      /// keep in mind. If you have any large custom object structures it is best
      /// to traverse these structures key by key and remove each element. Things
      /// to read up on would be 'Javascript memory leaks', 'javascript closures' 
      /// and 'garbage collection'. It is also best to keep in mind you can only
      /// nullify variables i.e. `var abc; abc = null;` -- you can not `delete abc`
      /// this is not a problem for properties i.e. `obj.prop = 123;` and is why
      /// it is best to use them for code you wish to tidy up later.
      delete window.one;
    }
    
    $(function(){
      /// trigger off whatever code you need onload
      /// this construction will never been kept by the
      /// javascript runtime as it is entirely anonymous 
      /// so you don't need to be worry about tidying it up.
    });
    

    上面的代码是手动输入的,所以可能会有错误,但它应该说明一种实现整洁加载系统的方法,该系统在每次加载时都能正确整理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-06
      • 1970-01-01
      • 1970-01-01
      • 2011-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多