ES6 模块如何取得自身 URL?

模块化的时候有这样一个问题。
通过自定义元素自制了一个滑块,其中 Shadow DOM 的 CSS 通过 @import 载入了一个外部的样式表。就需要知道 URL。大概这样:

// slider.js

const styleURL = "slider.css";

class SliderDiscrete extends HTMLElement {
    constructor () {
        super();

        const shadow = this.attachShadow({mode: 'open'});

        const style = document.createElement('style');
        style.innerText = `@import url(${styleURL})`;
        shadow.appendChild(style);
        ...
    }
    ...
}

export default SliderDiscrete;
// main.js

// Custom Element
import SliderDiscrete from './Components/slider/slider.js';
customElements.define('slider-discrete', SliderDiscrete);

我把 .css 和 .js 放在一起了。因为这样看起来好像合理一些。然后,如果 main.js 不传参,或者我自己不把路径写进去,slider.js 里的 SliderDiscrete 是不是就没有办法设 URL 了呢?

不是。网上变来的奇技淫巧有,搞一个 Error 对象。

const getFunctionLocation = function pathToTheScript() {
    const error = 0;
    const rgx = /(?:http|https|file):\/\/.*?\/.+?.js/;
    try {
        error.foo();
    } catch (e) {
        return rgx.exec(e.stack)[0];
    }
}

getFunctionLocation(); // "http://127.0.0.1/Components/slider/slider.js"

Chrome 在 Function 里面,有一个 [[FunctionLocation]],不知道能不能 直接 / 间接 获取。

现在是 2018 年了。ES9 都得学了。有什么新方法吗?

Stack Overflow 上的此类问题:

阅读 5.9k
4 个回答

嗯。ES6 get path of module inside module Stack Overflow 上早有了解答,之前不知道为什么漏掉了,。

好久不登 SF 今天登了重新看了一下搜了一下,17 年就有个 Stage 3 的提案,Chrome 64+ 已经支持。

module 内通过 import.meta 可获得一个含且仅含当前脚本 URL 的对象。

// slider.js
> import.meta
< {url: "http://127.0.0.1/Components/slider/slider.js"}

是十分完美 ؏؏☝ᖗ乛◡乛ᖘ☝؏؏

你的css肯定是放你自己的网站里的吧,你的域名你自己是知道的吧,不知道就用location.hostname获取,然后加上你自己的路径不就行了吗

对于非异步加载的 <script> 标签可以取到 src 的内容,配合当前页面的 window.location.pathname 可以得到 URL。但是 import 加载的……还真不清楚。一般确实需要 url 的会,我会把模块做成一个工厂方法,把通过其它方式取得的 url 传进去,用于计算。

既然已经发现了使用 Error 的方法可以获得,那就封装一下这个方法,让它只执行一次,减少开销就好,反正再多次 URL 也不会变。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题