如何在单页Web应用程序中处理多个脚本

时间:2012-10-18 14:27:56

标签: php javascript jquery

是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>

2 个答案:

答案 0 :(得分:2)

加载脚本的另一种方法:

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

答案 1 :(得分:2)

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

  1. 每当您在js中创建/导入结构时,请确保您已编码了一个unmport / destroy能力。
  2. 不要依赖通过.innerHTML$().html()插入的脚本标记 - 旧浏览器不尊重它们,这会导致意外结果 - 即脚本标记被忽略,或者旧版Internet Explorer ,试图从错误的地方装货。
  3. 而是以 thedev 推荐并以编程方式构建脚本标记。
  4. 如果你想让每个ajax的脚本返回相关的脚本标签,显然#3 很棘手。
  5. 因此,不是使用ajax请求返回纯HTML,而是返回包含HTML的JSON对象和需要加载的脚本路径列表。
  6. 如果您确保每个加载的脚本都通过特别命名的对象保留所有方法,则可以在下次加载下一个脚本时删除此对象。
  7. 以下是说明性代码,有更复杂的(和更好)处理此的方法(即避免在窗口上存储对象),以及以下代码可以在许多地方得到改善 - 它应该只是让你知道你能做什么,以及如何思考它。

    还应注意,在全局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.
    });
    

    以上代码已手动输入,因此可能存在错误,但它应说明实现整齐加载系统的一种方法,可以在每次加载时正确整理。