46

今天,我对 Javascript 中的相对路径的体验感到惊讶。我将情况归结为以下几点:

假设您有一个目录结构,例如:

app/
   | 
   +--app.html
   +--js/
        |
        +--app.js
        +--data.json

app.html所做的就是跑js/app.js

<!DOCTYPE html>
<title>app.html</title>
<body>
<script src=js/app.js></script>
</body>

app.js加载 JSON 文件并将其粘贴在开头body

// js/app.js
fetch('js/data.json') // <-- this path surprises me
  .then(response => response.json())
  .then(data => app.data = data)

数据是有效的 JSON,只是一个字符串:

"Hello World"

这是 . 的最小用法fetch,但令我惊讶的是,我传递给的 URLfetch必须是相对于app.html而不是相对于app.js. 我希望这条路径能够正常工作,因为data.jsonapp.js位于同一目录 ( js/) 中:

fetch('data.json') // nope

有没有解释为什么会这样?

4

3 回答 3

63

当您说fetch('data.json')您正在有效地请求http://yourdomain.com/data.json时,因为它与您发出请求的页面相关。您应该以正斜杠开头,这将表明该路径是相对于域根目录的:fetch('/js/data.json')。或完全质量与您的域fetch('http://yourdomain.com/js/data.json')

于 2016-04-02T05:27:42.537 回答
2

理解为什么会这样的一个简单方法是考虑如果我们在 中编写一个辅助函数会发生什么app/js/helper/logfetch.js

// app/js/helper/logfetch.js
function logFetch(resource) {
    console.log('Fetching', resource);
    return fetch(resource);
}

现在,考虑如果我们使用 logFetch from 会发生什么app/js/app.js

// app/js/app.js
fetch('data.json');    // if this is relative to js/, then ...
logFetch('data.json'); // should this be relative to js/ or js/helper/?

我们可能希望这两个调用返回相同的东西——但是如果 fetch 是相对于包含的文件,那么 logFetch 将请求js/helper/data.json而不是与 fetch 一致的东西。

如果 fetch可以感知从哪里调用它,那么为了实现诸如 logFetch 之类的辅助库,JavaScript需要一系列新的调用者位置感知功能。

相比之下,相对于 HTML 文件执行提取提供了更高的一致性。

CSS 的工作方式不同,因为它没有方法调用的复杂性:您不能创建转换其他 CSS 模块的“辅助 CSS 模块”,因此相对路径的概念在概念上更加清晰。

于 2021-01-21T23:01:13.893 回答
2

这并不完全是一个建议,因为它依赖于一些不能保证在任何地方都可以工作或在未来继续工作的东西,但是它在我需要的地方对我有用,它可能会对你有所帮助。

const getRunningScript = () => {
    return decodeURI(new Error().stack.match(/([^ \n\(@])*([a-z]*:\/\/\/?)*?[a-z0-9\/\\]*\.js/ig)[0])
}

fetch(getRunningScript() + "/../config.json")
  .then(req => req.json())
  .then(config => {
    // code
  })

于 2020-07-02T19:12:12.820 回答