85

require 和 import 详解

 5 years ago
source link: http://raoenhui.github.io/es6/2018/12/06/import/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前言

JS模块化编程是前端小伙伴们必不可少的知识,下面妹子将于自认为比较清晰的方式列举出来。

1 require

特点:

  • 1.运行时加载
  • 2.拷贝到本页面
  • 3.全部引入

1.1 CommonJS

Node.js就是用CommonJS思想。 在CommonJS中,有一个全局性方法require(),用于加载模块。

1.1.1 用法

var math = require('math');
math.add(2, 3);
var math = require('math');
const Math = new math(2, 3)
Math.add();

1.1.2 模块写法

模块写法分exports和module.exports。

exports.add = (x,y) => x+y;
module.exports = class math {
  constructor(x,y) {
    this.x = x;
    this.y = y;
  }

  add() {
    return  x+y;
  }
};

1.2 AMD

require.js和cujo.js就是用AMD思想。

AMD是”Asynchronous Module Definition”的缩写,意思就是”异步模块定义”。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

第二行math.add(2, 3),在第一行require(‘math’)之后运行,因此必须等math.js加载完成。也就是说,如果加载时间很长,整个应用就会停在那里等。 这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于”假死”状态。 因此,浏览器端的模块,不能采用”同步加载”(synchronous),只能采用”异步加载”(asynchronous)。这就是AMD规范诞生的背景。

1.2.1 用法

//require([module], callback);
require(['math'], function (math) {
 math.add(2, 3);
});

1.2.1 模块写法

define(id?, dependencies?, factory)

  • id:字符串,模块名称(可选)
  • dependencies: 是我们要载入的依赖模块(可选),使用相对路径。,注意是数组格式
  • factory: 工厂方法,返回一个模块函数

一个模块不依赖其他模块写法

// math.js
  define(function (){
    var add = function (x,y){
      return x+y;
    };
    return {
      add: add
    };
  });

模块还依赖其他模块

define(['Lib'], function(Lib){
    function foo(){
      Lib.doSomething();
    }
    return {
      foo : foo
    };
  });

当require()函数加载上面这个模块的时候,就会先加载Lib.js文件。

1.3 CMD

sea.js就是用CMD思想。 CMD是”Common Module Definition”的缩写。类似于requirejs,seajs是执行时发现需要依赖模块再异步加载,requirejs异步加载定义依赖模块后再执行。

1.3.1 用法

seajs.config({
  alias: {
    'jquery': 'http://modules.seajs.org/jquery/1.7.2/jquery.js'
  }
});

seajs.use(['./hello', 'jquery'], function(hello, $) {
  $('#beautiful-sea').click(hello.sayHello);
});

1.3.1 模块写法

define(function(require, exports, module) {
  var $ = require('jquery');

  exports.sayHello = function() {
    $('#hello').toggle('slow');
  };
});

2 import

特点:

  • 1.编译时加载
  • 2.只引用定义
  • 3.按需加载

推荐用 import 取代 require

2.1.1 用法

import有两种模块导入方式:命名式导入(名称导入)和默认导入(定义式导入),以及 import()

import defaultMember from "module-name";
import * as name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import defaultMember, { member [ , [...] ] } from "module-name";
import defaultMember, * as name from "module-name";
import "module-name";
  • name-从将要导入模块中收到的导出值的名称
  • member, memberN-从导出模块,导入指定名称的多个成员
  • defaultMember-从导出模块,导入默认导出成员
  • alias, aliasN-别名,对指定导入成员进行的重命名
  • module-name-要导入的模块。是一个文件名
  • as-重命名导入成员名称(“标识符”)
  • from-从已经存在的模块、脚本文件等导入

import()

import()返回一个 Promise 对象。

// 报错
if (x === 2) {
  import MyModual from './myModual';
}

引擎处理import语句是在编译时,这时不会去分析或执行if语句,所以import语句放在if代码块之中毫无意义,因此会报句法错误,而不是执行时错误。没办法像require样根据条件动态加载。 于是 提案 引入import()函数,编译时分析if语句,完成动态加载。

if(x === 2){
  import('myModual').then((MyModual)=>{
    new MyModual();
  })
}

2.2.1 模块写法

export有两种模块导出方式:命名式导出(名称导出)和默认导出(定义式导出),命名式导出每个模块可以多个,而默认导出每个模块仅一个。

export { name1, name2, …, nameN };
export { variable1 as name1, variable2 as name2, …, nameN };
export let name1, name2, …, nameN; // also var
export let name1 = …, name2 = …, …, nameN; // also var, const
 
export default expression;
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };
 
export * from …;
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
  • name1… nameN-导出的“标识符”。导出后,可以通过这个“标识符”在另一个模块中使用* import引用
  • default-设置模块的默认导出。设置后import不通过“标识符”而直接引用默认导入
  • -继承模块并导出继承模块所有的方法和属性
  • as-重命名导出“标识符”
  • from-从已经存在的模块、脚本文件…导出

参考资料

Happy coding .. :)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK