无法找到模块“mint-ui”的声明文件_新版本javascript ES6模块化看完这些就知道多香了...

ES6 模块简介

ES6以前 实现模块化用 RequireJS 或 seaJS(分别是基于AMD 规范的模块化库,和基于 CMD 规范的模块化库)。

ES6 引入了模块化,其设计思想是在编译时就能确定模块的依赖关系,及输入和输出的变量。

ES6 的模块化分为导出(export) @与导入(import)两个模块。

ES6 的模块自动开启严格模式,不管你有没有在模块头部加上 use strict;

可导入和导出各种类型的变量(如函数,对象,字符串,数字,布尔值,类等)

各模块都有自己的上下文,每一个模块内声明的变量都是局部变量,不会污染全局作用域。

每个模块只加载一次(是单例的, 若再去加载同目录下同文件,直接从内存中读取。)

模块的原理

就是一个独立文件

文件内部的所有变量,外部无法获取,须用export输出。

export 与 import

• 导出的函数声明与类声明必须有名称(export default 除外)。

• 不仅能导出声明还能导出引用(例如函数)。

• export 可以出现在模块的任何位置,但必需处于模块顶层。

• import 会自动提升到模块头部,先执行。

/*-----export [test.js]-----*/

let myName = "Tom";

let myAge = 20;

let myfn = function(){

return "My name is" + myName + "! I'm '" + myAge + "years old." }

let myClass = class myClass {

static a = "yeah!";

}

export {

myName, myAge, myfn, myClass

}

/*-----import [xxx.js]-----*/

import { myName, myAge, myfn, myClass } from "./test.js";

console.log(myfn());

// My name is Tom! I'm 20 years old. console.log(myAge);

// 20 console.log(myName);

// Tom console.log(myClass.a );

// yeah!

建议使用大括号指定所要输出的一组变量写在文档尾部,明确导出的接口。

函数与类都需要有对应的名称,导出文档尾部也避免了无对应名称。

export 导出变量

要外部读取模块内的变量,必用export。

例如:用export对外部输出三个变量:

export var firstName = 'Michael';

export var lastName = 'Jackson';

export var year = 1958;

建立对应关系

(提供对外的接口)

// 报错:只是一个值,不是接口

export 1;

// 报错

var m = 1;

export m;//此处并不是声明的变量,而是m的值

//正确

export var m = 1;

var m = 1;

export {m};

var n = 1;

export {n as m};

简写

var firstName = 'Michael';

var lastName = 'Jackson';

var year = 1958;

export {firstName, lastName, year};

export let

// path.js

export default { a:1 };

export let b = 2;

export let c =3;

输出动态值

即通过该接口,可以取到模块内部实时的值。

export var foo = 'bar';

setTimeout(() => foo = 'baz', 500);

上面代码输出变量foo,值为bar,500 毫秒之后变成baz。

与 CommonJS 规范完全不同。

CommonJS 模块输出的是值的缓存,不存在动态更新

export可出现在模块的任何位置,只要处于模块块级顶层就可以。

function foo() {

export default 'bar'

}

foo()

导出函数或类

export function multiply(x, y) {

return x * y;

};

导出格式

// 正确

export function f() {};

// 正确

function f() {}

export {f};

导出重命名

用as。

不同模块导出接口名命名重复,用 as 重新定义变量名。

function v1() { ... }

function v2() { ... }

export {

v1 as streamV1,

v2 as streamV2,

v2 as streamLatestVersion

};

v2可以用不同的名字输出两次

实例:

Tom 用 as 重新定义导出的接口名称,隐藏模块内部的变量

/*-----export [test.js]-----*/

let myName = "Tom";

export { myName as exportName }

/*-----import [xxx.js]-----*/

import { exportName } from "./test.js";

console.log(exportName);

导入重命名

/*-----export [test1.js]-----*/

let myName = "Tom";

export { myName }

/*-----export [test2.js]-----*/

let myName = "Jerry";

export { myName }

/*-----import [xxx.js]-----*/

import { myName as name1 } from "./test1.js";

import { myName as name2 } from "./test2.js";

console.log(name1);// Tom

console.log(name2);// Jerry

export default

导出默认对象

export default 仅有一个

export default 中的 default 是对应的导出接口变量。

export default 向外暴露的成员,可用任意变量接收。

var a = "My name is Tom!";

export default a;// 仅有一个

export default var c = "error";//default 已经是对应的导出变量,不能跟着变量声明语句

import b from "./xxx.js";// 不需要加{}, 使用任意变量接收

export default 和 export 区别

相同点:

l 均可导出常量、函数、文件、模块等

不同点:

l 一个模块中,export、import可以有多个,export default仅能有一个

l export导出的,在导入时要加{ },export default不用

实例(export)

导出:a.js

export const str = "blablabla~";

export function log(sth) {

return sth;

}

导入:b.js

import { str, log } from 'a'; //也可以分开写两次,导入的时候带花括号

实例(export default)

导出:a.js

const str = "blablabla~";

export default str;

导入:b.js

import str from 'a'; //导入的时候没有花括号

实例:

export default为模块指定默认输出,就不需要知道所要加载模块的变量名

//a.js

let sex = "boy";

export default sex(sex不能加大括号)

其实相当于为sex变量值"boy"起了一个系统默认的变量名default,

自然default只能有一个值,所以一个文件内不能有多个export default。

// b.js

本质上,a.js文件的export default输出一个叫做default的变量,然后系统允许你为它取任意名字。

所以可以为import的模块起任何变量名,且不需要用大括号包含

import any from "./a.js"

import any12 from "./a.js"

console.log(any,any12) // boy,boy

复合使用

export 与 import 可在同一模块使用:

可将导出接口改名,包括 default。

复合使用 export 与 import ,也可以导出全部,

当前模块导出的接口会覆盖继承导出的。

export { foo, bar } from "methods";

// 约等于下面两段语句,不过上面导入导出方式该模块没有导入 foo 与 bar

import { foo, bar } from "methods";

export { foo, bar };

/* ------- 特点 1 --------*/

// 普通改名

export { foo as bar } from "methods";

// 将 foo 转导成 default

export { foo as default } from "methods";

// 将 default 转导成 foo

export { default as foo } from "methods";

/* ------- 特点 2 --------*/

export * from "methods";

import

import...from...的from后面可跟很多路径格式,

若只给出包名(如:vue,axios),会自动到node_modules目录加载;

若给出相对路径及文件前缀,则到指定位置寻找。

可加载各种各样的文件:.js、.vue、.less等。

可省略掉from直接引入。

ES6的import...from...不需要指明文件后缀。

实例1

import Vue from 'vue';

其实最完整的写法是:

import Vue from "../node_modules/vue/dist/vue.js";

因为main.js是在src文件中,所以../向前一级相对目录查找node_modules,再依次寻找后面的文件。

实例2

import axios from 'axios';

完整意思是:

import axios from '..ode_modulesaxiosdistaxios.js';

和引入vue文件是一样的原理,都是从node_modules中加载相应名称的模块。

实例3

import App from './App';

完整写法:

import App from './App.vue';

意思是:

引入写好的.vue文件。(.vue文件是vue框架的单文件组件。)

实例4

import router from './route';

完整写法:

import router from './route.js';

意思是:

引入和main.js同级目录下的route.js文件。

实例5

import './less/index';

意思是:

import './less/index.less';

import 命令

用export命令定义了模块的对外接口以后,其他 JS 文件就可通过import加载这个模块。

// main.js

import {firstName, lastName, year} from './profile.js';

function setName(element) {

element.textContent = firstName + ' ' + lastName;

}

上面代码的import命令,用于加载profile.js文件,并从中输入变量。

import接受一对大括号,里面指定要从其他模块导入的变量名。

大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。

导入重命名

如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名。

import { lastName as surname } from './profile.js';

import输入的变量都是只读的,因为它的本质是输入接口(不允许在加载模块的脚本里面改写接口)。

import {a} from './xxx.js'

a = {}; // Syntax Error : 'a' is read-only;

上面代码中,脚本加载了变量a,对其重新赋值就会报错,因为a是一个只读的接口。

如果a是对象,改写a的属性是允许的。

import {a} from './xxx.js'

a.foo = 'hello'; // 合法操作

上面代码中,a的属性可以成功改写,并且其他模块也可以读到改写后的值。

不过,这种写法很难查错,建议凡是输入的变量,都当作完全只读,轻易不要改变它的属性。

import后面的from指定模块文件的位置,可以是相对路径,也可以是绝对路径,.js后缀可以省略。

如果只是模块名,不带有路径,那么必须有配置文件,告诉 JavaScript 引擎该模块的位置。

import {myMethod} from 'util';

上面代码中,util是模块文件名,由于不带有路径,必须通过配置,告诉引擎怎么取到这个模块。

import命令具有提升效果,会提升到整个模块的头部,首先执行。

foo();

import { foo } from 'my_module';

上面的代码不会报错,因为import的执行早于foo的调用。

这种行为的本质是,import命令是编译阶段执行的,在代码运行前。

import是静态执行

由于import是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构。

// 报错

import { 'f' + 'oo' } from 'my_module';

// 报错

let module = 'my_module';

import { foo } from module;

// 报错

if (x === 1) {

import { foo } from 'module1';

} else {

import { foo } from 'module2';

}

上面三种写法都会报错,因为用到了表达式、变量和if结构。

在静态分析阶段,这些语法都是没法得到值的。

最后,import语句会执行所加载的模块,因此可以有下面的写法。

import 'lodash';//执行lodash模块,但是不输入任何值。

如果多次重复执行同一句import语句,那么只会执行一次。

import 'lodash';

import 'lodash';

上面代码加载了两次lodash,但是只会执行一次。

import { foo } from 'my_module';

import { bar } from 'my_module';

// 等同于

import { foo, bar } from 'my_module';

上面代码中,虽然foo和bar在两个语句中加载,但是它们对应的是同一个my_module实例。也就是说,import语句是 Singleton 模式。

目前阶段,通过 Babel 转码,CommonJS 模块的require命令和 ES6 模块的import命令,可写在同一个模块里面(但是最好不要这样做)。

因为import在静态解析阶段执行,所以它是一个模块中最早执行的。

下面的代码可能不会得到预期结果。

require('core-js/modules/es6.symbol');

require('core-js/modules/es6.promise');

import React from 'React';

感谢收看本期Q程序员说,最后别忘点赞加关注哈!我接着继续整,有啥不爽留言。

687963bb4b3e1935f8c79706c2126946.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值