【问题标题】:Running javascript code called by AJAX运行由 AJAX 调用的 javascript 代码
【发布时间】:2012-03-03 18:37:12
【问题描述】:

我的网站使用 pushState 来加载页面。我有一个问题,我想在其中一个页面上使用 javascript,但不能,因为它使用 AJAX 加载所有内容。那我该怎么办?有人告诉我有关“parseScript”的一些信息,但我找不到足够的信息。

--示例--

我使用 AJAX 加载 在我的页面上,我有这个脚本:

<script type="text/javascript">
        function go(){
            alert('1');
        }
    </script>
<a href="javascript:void();" onClick="go();">GO!!!</a>

什么都没有发生。

--编辑--

如果我打开 Google Chrome 的调试器: “未捕获的 ReferenceError:未定义 go” 而且

【问题讨论】:

  • 它认为你在寻找 eval()
  • 我不确定您为什么不能对通过 Ajax 加载的内容使用 JavaScript。您能否更具体地说明您遇到的问题?

标签: javascript ajax parsing pushstate


【解决方案1】:

我认为对如何进行 Ajax 调用和加载内容有更多的详细信息会很有帮助。也就是说,有几点需要注意:

  • javascript:void() 的语法无效。它应该是 javascript:void(0)。就此而言,在锚标记的 href 上使用 javascript:void() 通常是不好的做法。有些浏览器不支持它。如果必须使用标签,请将 href 设置为 # 并添加“return false;”到点击事件。
  • 在这种情况下,无论如何你都应该使用按钮标签而不是 a 标签。
  • 根据您提供的内容,它应该可以工作(除了 void() 的语法错误)

【讨论】:

    【解决方案2】:

    浏览器似乎无法解析通过targetElement.innerHTML 添加到文档中的&lt;script&gt; 元素内容。这可能就是您遇到的问题。

    最好的解决方案是使用经过良好测试的框架(如 jQuery)来解决此类问题。他们已经弄清楚了如何安全、正确地将脚本注入 DOM。除非您绝对不能为图书馆腾出带宽,否则重新发明轮子是没有意义的。


    解决此问题的一种方法是在 Ajax 响应中将 JavaScript 与 HTML 分开,方法是发出两个请求(可能更慢)或在 JSON 对象中构建 JavaScript 和 HTML(可能更难维护)。

    这是一个例子:

    <script>
    
    function load_content(){
      var req = new XMLHttpRequest();
      req.open("GET", "ajax.json", true);
      req.onreadystatechange = function (e){
        if (req.readyState === 4){
          if (req.status === 200){
    
            // these three lines inject your JavaScript and
            // HTML content into the DOM
            var json = JSON.parse(req.responseText);
            document.getElementById("target").innerHTML = json.html;
            eval(json.js);
          } else {
            console.log("Error", req.statusText);
          }
        }
      };
      req.send(null);
    }
    
    </script>
    
    <a href="#" onclick="load_content()">Load more stuff</a>
    <div id="target"></div>
    

    服务器上的文档ajax.json如下所示:

    {
      "js": "window.bar = function (){ console.log(\"bar\"); return false; }",
      "html": "<p><a href=\"#\" onclick=\"bar();\">Log a message</a></p>"
    }
    

    如果您选择此路线,您必须:

    • 给你的函数命名空间:MyApp.foo = function (){ ... };,或者
    • 将您的函数显式添加到全局命名空间:window.foo = function (){ ... };。

    这是因为eval 在当前作用域内执行,所以您的函数定义继承了该作用域并且不会全局可用。在我的示例中,我选择了后一个选项,因为它只是一个简单的示例,但您应该知道为什么这是必要的。

    如果您决定自己实施,请务必阅读When is JavaScript's eval() not evil?。

    【讨论】:

    • 永远不要使用 eval()。这是等待中的安全噩梦。相反,构建系统以便客户端函数处理 json 结果。事实上,json 是一种轻量级的数据传输语言。它不是 JavaScript,也不打算这样使用。
    • “从不”有点过激。 jQuery 和 Prototype 都在某种程度上依赖 eval 来达到这个目的。是否有另一种方法可以将脚本注入 DOM?还是您专门指的是我使用eval 将JSON 字符串解析为本机对象?
    • 绝对不是为了将 json 解析成函数。同样,这是不好的做法。坦率地说,我从来没有使用过它,我正在处理一些非常复杂的东西。
    • 肯定有其他选项可以将脚本添加到 dom。从添加带有 src 引用的脚本元素,到使用 jsonp,再到使用可怕的 document.write(具有编写开始和结束脚本标签的已知技巧。您甚至可以使用服务器端代码生成 js 输出,只要它的内容类型返回为 application/javascript 或 text/javascript。
    • @MadManMoon 我更新了我的示例以使用 JSON.parse 并包含一些关于 eval 和滚动您自己的脚本注入的其他警告。
    【解决方案3】:

    如果我要这样做,我会使用 jquery 的加载调用。 这负责进行 ajax 调用,并为脚本/无脚本元素解析标签。

    如果您不想使用 jquery,我建议您上网查找 jquery load 方法的作用,并为您的 ajax 调用实现与事件处理程序相同的功能。

    【讨论】:

    • 我用这个 $.get('files/'+url+'.php', function(data,textStatus, xhr)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-10
    • 2017-10-22
    • 2016-09-27
    相关资源
    最近更新 更多