为了账号安全,请及时绑定邮箱和手机立即绑定

我可以将 javascript 模块与“常规”javascript 混合使用吗?

我可以将 javascript 模块与“常规”javascript 混合使用吗?

莫回无 2023-07-06 10:00:33
我有一个页面设置,它引用了几个 javascript 文件,并在页面中内嵌了一些 javascript,这是在加载页面时生成的。其中一个 JavaScript 文件包含来自第三方库的类。另一个 javascript 文件包含与页面相关的各种变量、事件处理程序和函数,它们使用第三方库 ( var v = new thirdPartyClass(parameters);) 中的类。第三方最近更新了他们的库并转而使用模块,因此现在他们不再提供可用的类,而是提供了可用的类导出。这是我第一次接触js模块。因此,据我了解,现在我必须从模块导入该类,而不是包含 js 文件。当我尝试这样做时,我收到一个控制台错误,只有模块可以导入。我添加type="module"到<script>我的js文件的标签(它已经添加到第三方js脚本标签),然后我可以导入他们的类,但现在我的函数无法从页面(function Uncaught ReferenceError: myFunction is not defined)访问。我不知道活动是否有效,因为它不会再发展到那么远了。有什么方法可以使用他们的新导出类,而不必将我的 js 文件完全重组为模块并更改页面以使用它?
查看完整描述

4 回答

?
杨__羊羊

TA贡献1943条经验 获得超7个赞

您可以创建一个脚本类型模块,导入所需的对象并将它们放入窗口中。{您的对象的名称}如下:


<script type="module">

    import { theItem } from "/path/to/module.js";

    window.theItem = theItem;

</script>

其余代码可以在常规 js 中。


查看完整回答
反对 回复 2023-07-06
?
慕容3067478

TA贡献1773条经验 获得超3个赞

您无法使用 . 在模块中创建全局变量var。要访问该函数,您可以将其从文件中导出:


export myFunction;

并将其导入到您需要的文件中:


import {myFunction} from "./relativeFilePath";

或者,如果您想从模块内创建全局变量,您可以将该变量直接放入对象中window:


window.myFunction = function() {

  //code

};


查看完整回答
反对 回复 2023-07-06
?
呼唤远方

TA贡献1856条经验 获得超11个赞

因此,据我了解,现在我必须从模块导入该类,而不是包含 js 文件。当我尝试这样做时,我收到一个控制台错误,只有模块可以导入。

对于传统的静态语句来说确实如此import

但是,值得注意的是,动态import()运算符(另一种导入模块的异步方式)可用于将模块导入到经典 javascript 文件以及其他模块中。

MDN注释:

import()语法通常称为动态导入,是一种类似函数的表达式,允许将 ECMAScript 模块异步动态加载到潜在的非模块环境中[...]

和:

[...]您可能需要使用动态导入:

  • 当您处于非模块环境中时(例如 [...]脚本文件)。

例子:


// /my-classic-javascript-file.js


const myAsyncFunction = async () => {

  const { myImportedClass } = await import('/path/to/module.js');

}

查看完整回答
反对 回复 2023-07-06
?
冉冉说

TA贡献1877条经验 获得超1个赞

属性window设置器解决方案:


<script type="module">

   import Dms from 'https://cdn.jsdelivr.net/npm/geodesy@2.4.0/dms.js';                 

   alert(Dms.toLat(-3.62, 'dms'));

   window.Dms = Dms;

</script>


<script>

  let Dms;

  Object.defineProperty(window, 'Dms', {

    get(){

      return Dms;

    },

    set(val){

      Dms = val;

      window.dispatchEvent(new Event('dms-set'));

    }

  });

  

  window.addEventListener('dms-set', () => alert('SECOND TIME: ' + Dms.toLat(-3.62, 'dms')));

  

</script>

一些承诺的解决方案:


<script type="module">

   import Dms from 'https://cdn.jsdelivr.net/npm/geodesy@2.4.0/dms.js';                 

   alert(Dms.toLat(-3.62, 'dms'));

   window.Dms = Dms;

</script>


<script>


  promisifyGlobal('Dms');

  

  Dms.then(Dms => alert('SECOND TIME: ' + Dms.toLat(-3.62, 'dms')));


  function promisifyGlobal(name){

    let global, promise = new Promise(resolve => {

      Object.defineProperty(window, name, {

        get(){

          return promise;

        },

        set(val){

          global = val;

          resolve(global);

        }

      });

    });

  }


</script>

您可以轻松地动态导入到非模块脚本中:


<script>


  (async () => {

    

    const {default: Dms} = await import('https://cdn.jsdelivr.net/npm/geodesy@2.4.0/dms.js');

    alert(Dms.toLat(-3.62, 'dms'));

  

  })();


</script>

最后是一些疯狂的通用解决方案:


<script type="module">


  import Dms from 'https://cdn.jsdelivr.net/npm/geodesy@2.4.0/dms.js'; 

  alert(Dms.toLat(-3.62, 'dms'));


</script>


<script>


  // this script will handle all imports 

  // tweak to import several exports and named exports


  for(const script of document.querySelectorAll('script[type=module]')) {

    

    const regex = /import\s+([^\s]+)\s+from\s+["\']([^"\']+)/g;

    let matches;

    while(matches = regex.exec(script.textContent)){

      const [, name, url] = matches;

      const src = `import ${name} from '${url}'; export default ${name};`;

      window[name] = new Promise(resolve => {

        import(`data:text/javascript, ${src}`).then(({default:imported}) => {

          setTimeout(() => resolve(imported));

        });

      });

    }


  }


</script>


<script>


  Dms.then(Dms => alert('SECOND TIME: ' + Dms.toLat(-3.62, 'dms')));


</script>


查看完整回答
反对 回复 2023-07-06
  • 4 回答
  • 0 关注
  • 125 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信