【问题标题】:Execute Script after append element from ajax callback从ajax回调追加元素后执行脚本
【发布时间】:2011-06-17 09:21:26
【问题描述】:

从一个 ajax 调用我得到一个 div 和一个用另一个 ajax 调用填充 div 的脚本。 问题是脚本运行时找不到 div。

这是剃须刀代码:

@model int

@{
    var id = string.Format("riga_{0}", Model);
}
<div id="@id">
    wait please...
</div>
<script type="text/javascript">
    $("#" + "@id").load("/RigaMovimento/Details/@Model");
</script>

生成这个:

<div id="riga_79">
    wait please...
</div>
<script type="text/javascript">
    $("#" + "riga_79").load("/RigaMovimento/Details/79");
</script>

回答

不漂亮,但有效:

@using (Ajax.BeginForm("Create", new { movimentoId = Model.MovimentoId }, new AjaxOptions() { InsertionMode = InsertionMode.InsertAfter, UpdateTargetId = "righe", OnSuccess = "run_after" }))
{
    <input type="submit" value="New" />
}

<script type="text/javascript">
    var run_after;
</script>

创建视图:

@model int

@{
    var id = string.Format("riga_{0}", Model);
}

<div id="@id">
    wait please...
</div>
<script type="text/javascript">
    run_after = function () {
        $('#' + '@id').load(
            "/RigaMovimento/Details/@Model", 
            null, 
            function() { $('#' + '@id').fadeIn('slow'); } );
    }
</script>

【问题讨论】:

    标签: jquery asp.net ajax razor


    【解决方案1】:

    如果有人仍在为此苦苦挣扎,我想到了一个巧妙的解决方案。假设您正在进行 jQuery ajax 调用:

    $.ajax({
      type: 'GET',
      url: 'fragment.html',
      success: function(html) {
        $('body').append(html);
      }
    });
    

    假设fragment.html 看起来像这样:

    <div class="fillme">
    </div>
    <script type="text/javascript>
      $('.fillme').text('I am filled.');
    </script>
    

    那么div.fillme的期望状态是:

    <div class="fillme">
      I am filled.
    </div>
    

    但当然不会发生,因为 div 和脚本是同时附加的,因此 div.fillme 在脚本执行时不存在。那么,这个问题可以通过在 after 附加 div 后附加脚本来解决。注意下面这行代码:

    var $html = $(html);
    

    会放列表

    [<div class="fillme"></div>, <script type="text/javascript">...</script>]
    

    进入$html 变量。这些是功能齐全的 DOM 片段,尚未附加到 DOM。最重要的是,脚本还没有执行;当我们附加它时它会。我们将确保在附加 div 后附加它。下面是一些通用代码:

    $.ajax({
      type: 'GET',
      url: 'fragment.html',
      success: function(html) {
        var $html = $(html);
        var nonscripts = $html.filter(function() { return !$(this).is('script'); });
        var scripts = $html.filter(function() { return !$(this).is('script'); });
        $('body').append(nonscripts).append(scripts);
      }
    });
    

    就是这样,伙计们。

    编辑:这是一个更通用的解决方案,它简单地利用了$html 变量中的元素按照它们在 HTML 片段中出现的顺序列出的事实:

    $.ajax({
      type: 'GET',
      url: 'fragment.html',
      success: function(html) {
        $(html).each(function(i, element) {
          $('body').append(element);
        });
      }
    });
    

    【讨论】:

      【解决方案2】:

      试试这个

      <script type="text/javascript">
          $(function() {
              /* code */
          });
      </script>
      

      【讨论】:

      • 该函数在添加div之前执行。这意味着它找不到 div
      • 使用 jQuery 就绪语句“$(function() {”,所以脚本将在生成 html 后执行。如果 div 是通过 DOM 加载的,请参阅我的其他答案,无法弄清楚你的代码。&lt;div id="riga_79"&gt; wait please... &lt;/div&gt; &lt;script type="text/javascript"&gt; $(function() { $("#" + "riga_79").load("/RigaMovimento/Details/79"); }); &lt;/script&gt;
      【解决方案3】:

      如果 div 在 DOM 中,jQuery 无法在 HTML 中找到它。 如果你在一个事件上加载脚本,你可以像这样使用 jQuery.live

      $( 'element' ).live( 'click', function(){
           $("#" + "riga_79").load("/RigaMovimento/Details/79");
      });
      

      也许这可以工作(没有测试过)

      $( 'body' ).live( 'load', function() {
          $("#" + "riga_79").load("/RigaMovimento/Details/79");
      });
      

      否则像这样使用livequery plugin

      $("#" + "riga_79").livequery(function(){
           $(this).load("/RigaMovimento/Details/79");
      });
      

      【讨论】:

        【解决方案4】:

        $(--selector--).load 方法有一个额外的回调参数

        http://api.jquery.com/load/

        这是一个在您的 AJAX 响应完成后调用的函数。 但是,您在 AJAX 响应中返回的脚本部分默认不会被评估。

        你必须在这里应用一个小技巧。请在下面找到一个更新 javascript 模块,它有一个公共方法“评估”。此方法从 AJAX 响应中获取您的脚本并对其进行评估。

        var Updater = function ()
        {
            var module = {};
        
            function doEvaluation(response)
            {
                var elem = document.createElement('div');
                elem.innerHTML = response;
                $(elem).find('script').each(
                    function ()
                    {
                        if (this.src)
                        {
                            $('body').append(this);
                        }
                        else
                        {
                            var content = $(this).html();
                            eval(content);
                        }
                    });
            }
        
            module.evaluate = function (response, status)
            {
                if (status == "success")
                {
                    doEvaluation(response);
                }
            }
            return module;
        } ();
        

        您甚至可以在其中附加一个全新的 javascript(doEvaluation 方法中的 if 语句)。因此,您需要做的是添加上面的模块,以便它驻留在您的页面上。其次,您必须将您的第一个 AJAX 调用(返回的 PartialResult 现在已损坏)修改为类似于以下内容:

        $('--selector--').load('--url--', Updater.evaluate);
        

        $.get('--url--', function(data, status, xhr) 
        {
            /* other logic */
            Updater.evaluate(data, status);
        });
        

        你就完成了。请注意,下面的更新程序仅适用于 jQuery AJAX 调用。如果您使用的是 MicrosoftAjax 或 MicrosoftMvcAjax,那就另当别论了。

        【讨论】:

          猜你喜欢
          • 2015-12-24
          • 2014-09-25
          • 2015-12-09
          • 1970-01-01
          • 1970-01-01
          • 2016-04-06
          • 2017-05-16
          • 1970-01-01
          • 2016-07-14
          相关资源
          最近更新 更多