【问题标题】:jQuery templates in script tags disappear when loading partial HTML through AJAX通过 AJAX 加载部分 HTML 时,脚本标签中的 jQuery 模板消失
【发布时间】:2010-11-28 10:45:16
【问题描述】:

我的 jQuery tmpl 插件有问题。

这是一个供您尝试的测试用例(因为 console.log 无法在没有 Firebug 的 Internet Explorer 上运行)。

一个文件 ajaxed_tpl.html:

<div id="some_inner">
    <script id="my_tmlp" type="text/x-jquery-tmpl">
        <li>
            <img src="${imgSource}" alt="image" />
            <h2> ${username} </h2>
        </li>
    </script>

     <script type="text/javascript">
            alert('I am here!');
     </script>
</div>
<div> I don't need this through AJAX</div>

test.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="js/jquery.js"></script>
        <script type="text/javascript" src="js/jquery.tmpl.js"></script>
    </head>
    <body>
    <div id="response_cont"></div>
        <script type="text/javascript">

             $.ajax({
                  type: "GET",
                  url: "ajaxed_tpl.html",
                  cache: false,
                  success: function(data) {

                        // it is ok if I fill entire data into HTML
                        $("#response_cont").html(data);
                        console.log($("#my_tmlp").html());  
                 }
            });
        </script>
    </body>
</html>

这个加载正常 - 我收到警报并且模板 html() 看起来不错。

但我也得到了“我不需要通过 AJAX”这一行。所以很明显,我只需要加载 div id="some_inner" 的内部部分,但我还需要执行 Javascript,所以唯一的方法是在获取 some_inner div 之前将数据插入 DOM。

所以让我们稍微修改一下 test.html:

success: function(data) {
                        // I need only the certain element with all the scripts and templates inside
                        var evaledHtml =  $("<div>").html(data).find("#some_inner").html();
                        $("#response_cont").html(evaledHtml);

                        // at this point Javascripts got executed, I get that alert()
                        console.log($("#my_tmlp").html());  
                        // but the template script is gone - console logs null!!!  
                 }

哦,伙计,模板去哪儿了?为什么script标签里的javascript被执行了,而script标签里的模板不见了?

但是现在让我们修改 ajaxed_tpl.html 中的模板:

<div id="my_tmlp" style="display:none;">
        <li>
            <img src="${imgSource}" alt="image" />
            <h2> ${username} </h2>
        </li>
</div>

然后再次运行 test.html。耶!这次 console.log 输出我们的模板!看来,如果是在 div 标签里,是不会被撕掉的。

但是有一个问题。如果我将模板放在 div 中而不是脚本中,浏览器会搞砸我的

<img src="${imgSource}" alt="image" />

所以现在看起来像:

<img src="$%7BimgSource%7D" alt="image"> 

即使我只加载通过 AJAX 接收的部分数据,是否有任何方法可以正确加载模板(无需浏览器对那些 ${} 进行编码)?

为什么那些模板脚本标签被撕掉了?是谁在做的——浏览器还是 jQuery?

【问题讨论】:

  • 如果你只用$("#response_cont").html($("#some_inner", data)); 替换你的evaledHTML 行,你会得到什么?
  • console.log() 也适用于 Chrome(我猜是 Safari)和 Opera。
  • @David - 目前的方法使用.innerHTML,但因浏览器而异......它们剥离了不同的东西:)
  • @Nick Craver: $("#some_inner", data) 在这种情况下不起作用 - 它为空。这就是为什么我做了那个奇怪的 evaledHTML 事情——没有它我无法进入 div 并自动执行内部 JS。
  • @David:谢谢,我忘了只有 IE 是一个特例。编辑了帖子。

标签: jquery jquery-templates


【解决方案1】:

注意:下面使用http://plugins.jquery.com/project/getAttributes

此脚本的作用是从返回的数据中过滤掉任何脚本标签以进行后期处理。必须以某种方式重新添加脚本模板标签,以便 tmpl 正确处理它们。在添加 html 数据后插入其他脚本标记以解决任何 document.ready 调用。

//              remove any scripts from the data                
                var $data = $('<span />').append($(data).filter(':not(script)'));

//              find the scripts so they can be added post element appended. this fixes document.ready bugs
                var $scripts = $(data).filter('script');

//              capture template scripts and add them as scripts 
//              bit of a ball ache but still does the job.
                var $template_scripts = $scripts.filter('[type="text/x-jquery-tmpl"]');
                $template_scripts.each(function()
                    {   
                        var $script = $('<script />'),
                            attr = $.getAttributes($(this));
                        $script.attr(attr);
                        $data.append($script); 
                        $script.text($(this).html());
                    });

//              append the html
                $("#response_cont").html($data); 

//              finally add the scripts after the html has been appended to work around any $(document).ready declarations in your scripts
                $(document).append($scripts); 

【讨论】:

    猜你喜欢
    • 2011-01-13
    • 2010-12-20
    • 2023-04-06
    • 1970-01-01
    • 2011-08-01
    • 2016-03-12
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    相关资源
    最近更新 更多