zoukankan      html  css  js  c++  java
  • es Module

    在es module出现之前还有社区推出amd和cmd的规范,这两者还有其特定的编写方式,使用起来不算很方便。es module被官方推出来就成为了浏览器端实现模块化的一个很好的方案。
     
    想要在浏览器端使用 es module ,首先在 html 当中引入 js 文件的时候,就需要将script标签中的type设置为module
    index.html  
    <script src="b.js" type="module"></script>

    这样浏览器才能执行使用es module的js文件,定义之后就可以在对应的js文件中使用模块化的方式来编写文件,导出和导入的方式有几种,但都是相同的关键字,export 与 import,一起来看看可以如何定义导入导出。

     
    第一种,直接导出定义的变量,这种方式导出的内容互不关联,适用于导出自己定义的常量,redux中定义action就经常使用这种导出
    复制代码
    a.js
    export const name = 'alice'
    export const age = 16
    

    b.js
    import { name, age } from "./a.js";
    console.log(name, age)
    // alice 16

    复制代码

    第二种,先定义变量,再使用 export 一起导出,导入方式可以使用上面的方式,也可以通过一个 * 来将所有的导出内容定义为一个对象,从对象中再去取值 ,redux中定义的reducer、action在 index.js 中导出会经常使用这种方式

    复制代码
    a.js
    const name = 'alice'
    const age = 16
    export { name, age }
    

    b.js
    import * as obj from "./a.js";
    console.log(obj.name, obj.age)
    // alice 16

    复制代码

    第三种,给导出的变量取别名,导入的变量同样可以取别名,当名字发生冲突时、导出变量名太长时,都可以取个别名,取完别名之后,原先的名字就不可用了

    复制代码
    a.js
    const name = 'alice'
    const age = 16
    

    export { name as myName, age as myAge }

    b.js
    import { myName as aliceName, myAge } from "./a.js";

    console.log(aliceName, myAge) // alice 16

    复制代码

    第四种,默认导出,默认导出在一个js文件中只允许存在一个,默认导出可以不用定义变量名,在导入的时候可以随意起名,并且导入的时候不需要加 {} ,这样的定义方式在编写redux中的reducer函数时很常见

    复制代码
    a.js
    export default function(){
        return 'hello world'
    }
    

    b.js
    import foo from './a.js'

    console.log(foo()) // hello world

    复制代码

    第五种,合并导出,在b.js文件导入a.js文件中导出的内容,b.js文件不对导入的内容做任何操作,直接导出,最后由index.js导入b.js并进行处理

    复制代码
    a.js
    export const name = 'alice'
    

    b.js
    export { name } from './a.js'

    index.js
    import { name } from './b.js'

    console.log(name) // alice

    复制代码

    以上是es module的具体的语法表现,导入导出的方式有很多,可以根据具体需要的场景进行判断和使用,另外,es module 还有一些特点。

    1、异步加载,当script标签中定义 type="module"之后,相当于给js标签加上了 async 的标识,代表异步加载资源,不会阻塞其它内容的执行,按照如下代码,打印的hi有可能是在引入的index.js文件之前,要根据 index.js 的执行速度来判断。
    <script src="index.js" type="module"></script>
    <script type="text/javascript">
        console.log('hi')
    </script>
     

    2、编译时解析,简单来说javascript的执行过程需要将原代码编译成抽象语法树,运行的时候再转成机器可识别的语言,在编译阶段解析数据,并不知道该不该加载此js文件,只有等到文件运行时,才知道文件里具体逻辑的执行过程,所以不能够在编译时解析的模块化方式出现类似条件判断,动态引入等代码

    const flag = true
    if(flag){
        import xxx from './a.js'
     }

    如果真的需要根据一些条件才执行代码,可以通过 require 函数来动态的引入,require函数执行完是一个promise对象,可以通过then方法来获取所需要的数据

    复制代码
    const flag = true
    

    if(flag){
    import(
    './b.js')
    .then(({name})
    =>{
    console.log(name)
    })
    }

    复制代码
    3、export 关键字后面跟的大括号并不是代表对象,在对象中也没有通过 as 取别名这样的方式,如果我们尝试以下把它当成对象来导出,一定是会报错的
    let name = 'alice'
    export {
        name: name
    }

     
     export 导出的 name 就对应着 name 这个变量,如果修改 name 的值,export 导出的内容会发生变化,import 导入的内容也会发生变化
    复制代码
    a.js
    let name = 'kiki', age = 18
    

    setTimeout(()=>{
    name
    = '嘻嘻嘻'
    },
    1000)

    export {
    name,
    age
    }

    b.js
    import { name, age } from './a.js'

    console.log(name)

    setTimeout(()=>{
    console.log(name)
    },
    2000)

    // 依次打印 kiki 嘻嘻嘻

    复制代码

    export 导出的内容有一个模块环境记录,用来记录导出时更改的变量,当变量更改时,使用新的变量值替换旧变量值

     
    但是不可以反向的修改,因为 import 导入的内容是一个通过 const 定义的常量,常量是不可以被修改的,以下操作是不可行的
    import { name } from './a.js'
    name = '哈哈哈哈'

      
    一般而言,我们都是在浏览器端使用 es module,如果想要在 node 端编写es module代码,可以有两种方式,一种是在 package.json 中配置 type:module,另一种是直接把js文件的后缀名为改为 .mjs
     
     
    node端常用的模块化方式是 commonjs,同样是模块化,那么 es module 和 commonjs 之间是否能互相调用呢,看看如下代码
    复制代码
    a.mjs
    const name = 'alice'
    const age = 18
    

    export {
    name,
    age
    }

    b.js
    const a = require('./a.mjs')

    console.log(a)

    复制代码

    以上代码执行会报错 Must use import to load ES Module,而如下的方式在高版本的nodejs中是可以的

    复制代码
    a.js
    const name = 'alice'
    const age = 18
    

    module.exports = {
    name,
    age
    }

    b.js
    import b from './b.js'

    console.log(b) // { name: 'alice', age: 18 }

    复制代码

    以上就是浏览器端模块方式es module的概念与用法,模块化能够更好的将代码分块并复用,nodejs端也有常用实现模块化的方式,即commonjs,如果不熟悉可以看看这篇文章 -> nodejs端模块化方式comomjs详解

    转载自: https://www.cnblogs.com/vigourice/p/14905096.html

  • 相关阅读:
    WORD2003电子签名插件(支持手写、签章)
    苹果App部署HTTPS进行在线下载安装
    解决安卓SDK更新连不通问题
    部署rfc5766-turn-server--谷歌推荐的开源穿透服务器 [复制链接]
    实测可用的免费STUN服务器!
    seajs加载jquery时提示$ is not a function该怎么解决
    tomcat发布web service教程
    Java WebService 简单实例
    HTML 5 断点续上传
    MySQL said: Authentication plugin 'caching_sha2_password' cannot be loaded
  • 原文地址:https://www.cnblogs.com/94-Lucky/p/15353330.html
Copyright © 2011-2022 走看看