简体   繁体   English

Javascript 中的相对路径

[英]Relative paths with fetch in Javascript

I was surprised by an experience with relative paths in JavaScript today.今天我对 JavaScript 中的相对路径的体验感到惊讶。 I've boiled down the situation to the following:我将情况归结为以下几点:

Suppose you have a directory structure like:假设您有一个目录结构,例如:

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

All my app.html does is run js/app.js我的app.html所做的就是运行js/app.js

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

app.js loads the JSON file and sticks it at the beginning of 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)

The data is valid JSON, just a string:数据有效JSON,只是一个string:

 "Hello World"

This is a pretty minimal usage of fetch , but I am surprised that the URL that I pass to fetch has to be relative to app.html instead of relative to app.js .这是fetch的最小用法,但令我惊讶的是,我传递给fetch的 URL 必须相对于app.html而不是相对于app.js I would expect this path to work, since data.json and app.js are in the same directory ( js/ ):我希望这条路径能够工作,因为data.jsonapp.js位于同一目录( js/ )中:

 fetch('data.json') // nope

Is there an explanation for why this is the case?有没有解释为什么会这样?

When you say fetch('data.json') you are effectively requesting http://yourdomain.com/data.json since it is relative to the page you're are making the request from.当您说fetch('data.json')时,您实际上是在请求http://yourdomain.com/data.json因为它与您发出请求的页面相关。 You should lead with forward slash, which will indicate that the path is relative to the domain root: fetch('/js/data.json') .您应该以正斜杠开头,这将表明路径是相对于域根的: fetch('/js/data.json') Or fully qualify with your domain fetch('http://yourdomain.com/js/data.json') .或者完全符合您的域fetch('http://yourdomain.com/js/data.json')条件。

An easy way to understand why it must be the case is to consider what should happen if we write a helper function in app/js/helper/logfetch.js :理解为什么会这样的一个简单方法是考虑如果我们在app/js/helper/logfetch.js中编写一个帮助程序 function 会发生什么:

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

Now, consider what happens if we use logFetch from app/js/app.js :现在,考虑如果我们使用来自app/js/app.js的 logFetch 会发生什么:

 // 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/?

We might want these two calls to return the same thing - but if fetch is relative to the contained file, then logFetch would request js/helper/data.json instead of something consistent with fetch.我们可能希望这两个调用返回相同的东西 - 但如果 fetch 是相对于包含的文件,那么 logFetch 将请求js/helper/data.json而不是与 fetch 一致的东西。

If fetch could sense where it is called from, then to implement helper libraries such as logFetch, the JavaScript would need a whole range of new caller-location-aware functionality.如果 fetch可以感知从哪里调用它,那么为了实现诸如 logFetch 之类的帮助程序库,JavaScript需要一系列新的调用者位置感知功能。

In contrast, performing the fetch relative to the HTML file provides more consistency.相比之下,相对于 HTML 文件执行提取可提供更高的一致性。

CSS works differently because it doesn't have the complexity of method calling: you can't create "helper CSS modules" that transform other CSS modules, so the idea of relative paths is a lot more conceptually cleaner. CSS 的工作方式不同,因为它没有方法调用的复杂性:您不能创建“帮助 CSS 模块”来转换其他 CSS 模块,因此概念上的相对路径更清晰。

This is not exactly a recommendation since it relies on a number of things that aren't guaranteed to work everywhere or to continue to work into the future, however it works for me in the places I need it to and it might help you.这并不完全是一个建议,因为它依赖于一些不能保证在任何地方都可以工作或在未来继续工作的东西,但是它在我需要的地方对我有用,它可能会对你有所帮助。

 const getRunningScript = () => { return decodeURI(new Error().stack.match(/([^ \n\(@])*([az]*:\/\/\/?)*?[a-z0-9\/\\]*\.js/ig)[0]) } fetch(getRunningScript() + "/../config.json").then(req => req.json()).then(config => { // code })

I was surprised by an experience with relative paths in Javascript today.今天,我对Java相对路径的使用感到惊讶。 I've boiled down the situation to the following:我将情况归结为以下几点:

Suppose you have a directory structure like:假设您有一个目录结构,例如:

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

All my app.html does is run js/app.js我所有的app.html都运行js/app.js

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

app.js loads the JSON file and sticks it at the beginning of body : app.js加载JSON文件并将其app.jsbody的开头:

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

The data is valid JSON, just a string:数据是有效的JSON,只是一个字符串:

"Hello World"

This is a pretty minimal usage of fetch , but I am surprised that the URL that I pass to fetch has to be relative to app.html instead of relative to app.js .这是一个相当小的使用fetch ,但我感到奇怪的是,我传递给URL fetch必须是相对于app.html ,而不是相对于app.js I would expect this path to work, since data.json and app.js are in the same directory ( js/ ):我希望此路径能正常工作,因为data.jsonapp.js位于同一目录( js/ ):

fetch('data.json') // nope

Is there an explanation for why this is the case?是否有这种情况的解释?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM