关于 import 和 export 的一些小技巧

3,070 阅读3分钟

default 的使用

我们都知道,如果一个类库在export时提供了default,即:

export default xxlib`

那么我们就能够直接使用

import xxlib from "xxlib"

这样的方式,而如果直接

export {method}`或`export const method = xxx

则引入方式只能是

import {method} from "xxlib"

而如果想将xxlib中所有的方法引入到一个变量中,则可以使用:

import * as xxlib from "xxlib"

这时,export default xxx导出的方法,则会包含在xxlibdefault字段下。

import 中的解构赋值

假设又一个文件student.js:

// student.js
export default {
    name: "bili",
    age: 16
}

我们想在score.js中引入:

// score.js
import student from "./student"

const {name} = student;
console.log(name);

这是完全ok的,但是当我们尝试在import时使用解构赋值,则会出现问题:

// score.js
import {name} from "./student"

console.log(name);

此时的name值是undefined,这是为什么呢?

原来,import中的解构与一般意义上的解构并不完全一致,我们的代码在经过babel转译之后会发生变化:

export default {
    name: "bili",
    age: 16
}

事实上会变成:

module.exports.default = {
    name: "bili",
    age: 16
}

也就是说,我们在import时,实际拿到的是:

{
    default: {
        name: "bili",
        age: 16
    }
}

这下我们就能明白为什么我们的解构赋值会不生效了。同时需要注意,我们在import student from "student"时,程序实际上会去自动获取student.jsdefault下的值,舅舅是为什么能够直接获取student的原因。

根据以上原理,我们如何才能实现import的解构赋值呢?其实很简单,只要我们能够将default下的值直接复制到module.exports下不就可以了吗?即实现以下操作:

module.exports = exports['default'];

当然这个过程已经有相应的插件babel-plugin-add-module-exports帮我们实现了,具体用法看文档即可,安装之后我们就能愉快的使用import的解构语法了:

import {name} from "./student"

export 导出解构对象

有时候我们需要批量导出已知类库的方法,这个时候我们使用export {module1, module2, ...}这样的方法就会显得非常繁琐,那么我们可不可以直接使用对象解构批量导出呢?类似这样:

import xxxlib from "xxxlib"

export {...xxxlib}

很遗憾,答案是不可以。因为export {module1, module2}中的{module11, module2, ...}实际上并不是一个对象,而是一个exports列表!。明白了吧,所以在这里使用解构是不成立的。

export default {...xxxlib}确是可以生效的,但缺点也很明显,无法在import时直接使用解构赋值获取,原因上面已经做过解释。

最后一种方案,我们如果直接使用module.exports,则可以实现类似的解构效果。

module.exports = {...xxxlib}

但是需要注意的是,新版本的babel不支持importmodule.exports的混合使用(但是requireexport的混用是支持的)。这意味着我们在使用module.exports时,只能够使用require来导入依赖文件了。

综上,目前还没有一个较为优雅的处理方式,期待以后能有更好的方案吧!

从类库直接 export 指定方法

有时候我们可能需要从某个包中直接导出某些方法,这时我们可以直接:

export {method1, method2} from "xxxlib"

这时method1method2将会同其它导出项一起export出去,非常简洁。