7

我有一个关于前端使用 JSON 和诸如此类的编码面试测验。我提交了我的文件,但我只想了解我缺少什么。

其中一项要求是Should not require a web server, and should be able to run offline..

我曾经jQuery并且曾经$.getJSON().JSON文件中获取数据。我把它放在我的WAMP本地服务器上,它可以在所有三种主要浏览器(IE、Firefox、Chrome)上完美运行。然后我把那个项目移到了Desktop,所以基本上没有本地服务器。

在 Firefox 30.0 上,它运行良好。没问题。

在 Google Chrome 上,我知道没有网络服务器就无法访问本地文件...

但是,在 Internet Explorer 11 上……它不起作用。为什么?

这是我正在使用的。这并不复杂。

function loadTasks() {
  console.log("Loading tasks...");
  $.getJSON("data.json", function(result) {
    $.each(result, function(i, task) {
      $("#load_tasks").append(
        "<div class='row'><span class='data-task'>" + task.name +
        "</span> <span class='data-date'>" + task.date +
        "</span> <span class='data-name'>" + task.assigned +
        "</span> </div>");
    });
  });
}

这是data.json

4

10 回答 10

6

这似乎是 jQuery 中的一个错误。此错误已报告给 jQuery。错误状态已修复。但似乎,这个错误仍然存​​在。

解释

一般在 IE 中,ajax 是通过ActiveXObjects实现的。但是在 IE11 中,他们对 ActiveXObject 的实现做了一些调整,如果我们尝试执行以下操作:

typeof(window.ActiveXObject)

而不是返回 'function',正如 IE 文档中所说,它返回undefined. jQuery 曾经使用它在普通浏览器中的 xhr 和 IE 中的 xhr 之间切换。由于检查评估为未定义,因此运行用于在普通浏览器中创建 xhr 对象的代码。(这当然是一个错误,奇怪的是,对于非本地文件它工作正常)。

提交给 bugs.jquery.com的一个错误中,错误报告者问道,

要解决问题,只需更改条件:使用“window.ActiveXObject !== undefined ?” 而不是“window.ActiveXObject?”

jQuery 开发人员确实尝试通过这个提交来解决这个问题,但是提交下的评论说它仍然没有修复,并且还提出了解决这个问题的可能方法。

var activex; // save activex somewhere so that it only need to check once
if ( activex === undefined ) 
  try { 
    new ActiveXObject("MSXML2.XMLHTTP.3.0");
    activex = true; 
  } catch (e) { 
    activex = false 
  }
xhr = activex ? createActiveXHR() : createStandardXHR(); 
于 2014-07-28T12:21:23.840 回答
3

我尝试在我的机器上运行你的代码,它在 IE 中运行良好。但是,如果这没有在您的机器上运行,则 IE 设置应该有一些问题。除此之外,如果您想读取本地文件,您可以尝试以下代码来解决 IE 的此问题

function showData(){
function getLocalPath(fileName/*file name assuming in same directory*/){
    // Remove any location or query part of the URL
    var directoryPath = window.location.href.split("#")[0].split("?")[0];
    var localPath;
    if (directoryPath.charAt(9) == ":") {
        localPath = unescape(directoryPath.substr(8)).replace(new RegExp("/","g"),"\\");
    }
    localPath = localPath.substring(0, localPath.lastIndexOf("\\")+1)+fileName;
    console.log(localPath);
    return localPath;
}

var content = null;
    try {
        var fileSystemObj = new ActiveXObject("Scripting.FileSystemObject");
        var file = fileSystemObj.OpenTextFile(getLocalPath("data.json"),1);
        content = file.ReadAll();
        file.Close();
    } catch(ex) {
        console.log(ex);
    }
    console.log(content);
}
showData();

从文件路径在浏览器中运行您的 html 文件,并尝试在控制台中运行上述功能。它将在控制台中输出 json 文件的内容。

您可以为上述代码创建一个包装器以在 XHR 请求中使用。如果您需要帮助将其与 jQuery AJAX 请求集成,请告诉我。

于 2014-08-02T11:03:11.267 回答
1

我们缺少的是 appCache 的使用,

<html manifest="example.appcache">

在您的 HTACCESS 添加

AddType text/cache-manifest .appcache

在example.appcache里面

CACHE MANIFEST
data.json
index.php
someimage.png
# continue for all the file needed for the web site to work

这意味着一旦您连接并下载了不再需要的内容。另一方面,您不应该file://通过 XHR/ajax 访问 URI,因为如果您希望它离线,则无法发送内容,您可以将 json 文件的内容作为字符串嵌入到您的代码中,然后使用var jsonStr = '{}'; var jsonObj = JSON.parse(jsonStr);哪里 jsonStr 是你的代码。这意味着没有与服务器的连接,因为没有 ajax/XHR 请求

于 2014-07-28T21:46:17.670 回答
1

jQuery .getJSON 使用 ajax。http://api.jquery.com/jquery.getjson/

.ajax 使用 XMLHttpRequest

chrome 和其他浏览器的 web 安全性会阻止 XMLHttpRequest 访问本地文件,因为这是一个安全问题。

通过深度安全:本地网页

http://blog.chromium.org/2008/12/security-in-depth-local-web-pages.html

您收到来自攻击者的电子邮件,其中包含您下载的网页作为附件。

您在浏览器中打开现在的本地网页。

本地网页创建一个 iframe,其来源为 https://mail.google.com/mail/

因为您已登录到 Gmail,所以框架会在您的收件箱中加载邮件。

本地网页通过使用 JavaScript 访问 frames[0].document.documentElement.innerHTML 来读取框架的内容。(互联网网页将无法执行此步骤,因为它来自非 Gmail 来源;同源策略会导致读取失败。)

本地网页将收件箱的内容放入 a 中,并通过表单 POST 将数据提交到攻击者的 Web 服务器。现在攻击者拥有了您的收件箱,这可能对发送垃圾邮件或识别盗窃有用。

不需要同源策略安全的数据的解决方案是填充 json。由于 jsonp 不是一种安全的数据格式。Jsonp 没有同源策略。

/* secured json */
{
  "one": "Singular sensation",
  "two": "Beady little eyes",
  "three": "Little birds pitch by my doorstep"
}

/* padded json aka jsonp */
Mycallback ({
  "one": "Singular sensation",
  "two": "Beady little eyes",
  "three": "Little birds pitch by my doorstep"
});

由于使用 jsonp,json 被包装在一个有效的 javascript 函数中,它可以像任何人将任何 javascript 添加到页面一样打开。

var element = document.createElement("script");
element.src = "jsonp.js";
document.body.appendChild(element);

你的回调处理数据,

function Mycallback(jsondata) {
}

这在功能上与ajax请求相同,但不同,因为它是一个jsonp请求,实际上更容易。

jQuery 库也直接支持 jsonp http://api.jquery.com/jquery.getjson/请参阅使用 Flickr 的 JSONP API 的示例;除非知道双重标准,否则他们甚至可能不会注意到正在使用 jsonp。

(function() { /* jsonp request note callback in url, otherwise same json*/
  var flickerAPI = "http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?"; 
  $.getJSON( flickerAPI, {
    tags: "mount rainier",
    tagmode: "any",
    format: "json"
  })
    .done(function( data ) {
      $.each( data.items, function( i, item ) {
        $( "<img>" ).attr( "src", item.media.m ).appendTo( "#images" );
        if ( i === 3 ) {
          return false;
        }
      });
    });
})();

可以启用对 json 的本地访问,但具体取决于浏览器。

使用 --allow-file-access-from-files 在 chrome 中启用它。https://code.google.com/p/chromium/issues/detail?id=40787

仅供参考:他们正在研究加密的 json https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-encryption-08我相当肯定不会有在本地使用它的方法目的是让它真的非常安全。

于 2014-08-03T08:27:20.857 回答
0

使用 JSONP,您可以使其适用于所有有或没有 Web 服务器甚至跨域的浏览器。

示例 data.jsonp 文件:

loadTasks([
    {name:"Task 1", date:"Date 1", assigned:"John Doe"},
    {name:"Task 2", date:"Date 2", assigned:"Jane Doe"}
]);

然后在您的页面上使用脚本标签加载 data.jsonp:

<script>
function loadTasks(tasks) {
    $.each(tasks, function (i, task) {
        $("#load_tasks").append(
            "<div class='row'><span class='data-task'>" + task.name +
            "</span> <span class='data-date'>" + task.date +
            "</span> <span class='data-name'>" + task.assigned +
            "</span> </div>");
    });  
}
</script>
<script src="data.jsonp"></script>
于 2014-08-01T20:24:35.233 回答
0

来源:https ://stackoverflow.com/a/22368301/1845953

发布答案以防万一其他人遇到它。在我的情况下,IE 正在加载一个明显导致“JSON 未定义”错误的 jquery 版本。这是我为解决它所做的:

<!--[if lt IE 9]>
    <script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<![endif]-->
<!--[if gte IE 9]><!-->
    <script src="http://code.jquery.com/jquery-2.0.3.js"></script>
<!--<![endif]-->

最新的是jquery 2.1.1直接链接,但它说:

(不支持 IE <9)

所以我猜jquery 1.11.1直接链接

而且我发现如果您使用带有此标志的 Chrome,您可以在 Chrome 中在本地文件上开发 ajax 和 jquery 内容:(--allow-file-access-from-files 来源)

于 2014-07-23T06:11:21.420 回答
0

这是一个有效的解决方案。我已经包括了车把,因为它更清洁。

<!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>JSON TEST</title>

    </head>
    <body>

        <div id="load-tasks">

        </div>


        <script src="jquery.min.js"></script>
        <script src="handlebars.min.js"></script>


        <script id="tasks-template" type="text/x-handlebars-template">
            {{#each .}}
            <div class="row">
                <span class="data-task">
                    {{this.name}}
                </span> <span class="data-date">
                    {{this.date}}
                </span> <span class="data-name">
                    {{this.assigned}}
                </span>
            </div>
            {{/each}}
        </script>

        <script>
            $(function () {
                var loadTasksContainer = $('#load-tasks'),
                    tasksTemplate = Handlebars.compile($('#tasks-template').html());

                $.ajax({
                    type: "GET",
                    url: "data.json",
                    dataType: "json",
                    cache: false,                    
                    success: function (data) {
                        var html = tasksTemplate(data);
                        loadTasksContainer.append(html);
                    },
                    error: function (xhr, status, error) {
                        //log error and status
                    }
                });

            });
        </script>
    </body>
    </html>
于 2014-07-28T08:53:29.477 回答
0

尝试包含error回调;jqxhr.responseText可能仍包含data.json.

数据.json

{"data":{"abc":[123]}}

json.html

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$(function() {
  $.getJSON(document.location.protocol + "data.json")
  .then(function(data, textStatus, jqxhr) {
    var response = JSON.parse(data);
    console.log(textStatus, response);
  } 
   // `error` callback
  , function(jqxhr, textStatus, errorThrown) {
      var response = JSON.parse(jqxhr.responseText);
      console.log(textStatus, errorThrown, response);
      $("body").append(response.data.abc);
  });
})
</script>
</head>
<body>
</body>
</html>
于 2014-08-02T04:56:11.020 回答
0
<meta http-equiv="X-UA-Compatible" content="IE=edge"> 

尝试添加此元标记并签入 IE

于 2014-07-28T08:46:22.393 回答
0

处理这个问题将把你带到任何地方。这是一项艰巨的任务,使用任何 http 服务器都可以轻松解决。

如果您的问题是难以设置,请尝试以下操作: https ://www.npmjs.org/package/http-server

在您的外壳上,您转到文件所在的目录,然后您只需键入

http-server ./ -p 12345 

where12345可以通过您选择的任何有效且尚未使用的端口进行更改。

于 2014-08-03T07:13:42.077 回答