模块化

1、NODEJS的common.js规范

1.1、module.exports

module.exports是node的私有的一个全局变量属性,测试发现可以用require引用,也可以用import from来使用。

//demo.js
let a= "字符串";
function func() {
    console.log("函数")
}
module.exports = {
    a,
    func
}

//module2
import util from './demo'
//let util=require('./demo')
//import {a,func} from './demo'
console.log(util)

/**
结果:
  {
    a:"字符串",
    func:function(){
      console.log("函数")
    }
  }
*/



1.2、exports

exports只是module.exports的全局引用 , 值得注意的是,你不能给exports赋值,这很重要,很重要,很重要。

//demo.js
// 错误写法
// exports={a:"aa"}
// 打印 {}


// 正确写法
exports.a = 10;
exports.func=function() {
    console.log("lalala")
}
// 打印 {a:10,func:function}

// 上面写了exports就不能写下面的module.exports,下面会覆盖上面的,因为exports指向module.exports
// module.exports = {a:"aaa"}

//main.js 引入,下面两种都可以
//第一种
import a from './demo'
//第二种
let a=require('./demo')

2、es6 module

2.1、export

  • 基本使用

模块功能主要由两个命令构成:exportimportexport命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

// demo.js 第一种写法
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
export function multiply(x, y) {
  return x * y;
};

//使用,需要哪个变量直接使用就好
import {firstName,year} from './demo'
console.log(firstName,year)

//打印
Michael 1958

2.2、注意点

2.2.1、import引入注意事项

上面代码的import命令,用于加载demo中输入变量。import命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。

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

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

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

像获取一个对象的形式获取


//错误
import utils from './demo' //utils为undefined
//正确,util可以自己更改命名
import * as util from './demo'

由于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';
}

会执行,但不会有任何结果

import 'lodash';
2.2.2、export导出注意事项
// 报错
export 1;

// 报错
var m = 1;
export m;


// 正确写法一
export var m = 1;

// 正确写法二
var m = 1;
export {m};

// 正确写法三
var n = 1;
export {n as m};

// 报错
function f() {}
export f;

// 正确
export function f() {};

// 正确
function f() {}
export {f};
2.2.3、动态变化数值

export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。

会自动变化

//demo.js
export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);

//main.js
import {foo} from './demo'

console.log(foo) //第一次打印为bar
setTimeout(()=>{
   console.log(foo) //第二次打印为baz
},1000)
2.2.4、export出现位置

export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错,下一节的import命令也是如此。这是因为处于条件代码块之中,就没法做静态优化了,违背了ES6模块的设计初衷

// 报错
function foo() {
    export default 'bar' // SyntaxError
  }
  foo()

//报错
{
    export let a=10;
}

2.3、export default

export default命令只能输出一个

从前面的例子可以看出,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。

为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。

// 第一组
export default function suibian() { // 输出
  // ...
}

import crc32 from 'crc32'; // 输入

// 第二组
export function crc32() { // 输出
  // ...
};

import {crc32} from 'crc32'; // 输入

3、webpack 之 require.context 用法

最近项目中用到了vue-element-admin当作框架,当中有一个很好的例子:封装了一个svg的组件,其中就是用到了require.context

3.1、基本语法

require.context有三个参数:
    directory:说明需要检索的目录
    useSubdirectories:是否检索子目录
    regExp: 匹配文件的正则表达式
require.context("./test", false, /\.test\.js$/);
//(创建了)一个包含了 test 文件夹(不包含子目录)下面的、所有文件名以 `.test.js` 结尾的、能被 require 请求到的文件的上下文。
require.context("../", true, /\.stories\.js$/);
//(创建了)一个包含了父级文件夹(包含子目录)下面,所有文件名以 `.stories.js` 结尾的文件的上下文。

封装svg里面用到的

//第一种用法
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', false, /\.svg$/)
requireAll(req)

//第二种用法
const context = require.context("./svg", true, /\.svg$/)
context.keys().map(context)

4、参考链接

手摸手,带你优雅的使用 icon https://juejin.im/post/59bb864b5188257e7a427c09

posted @ 2020-01-03 20:05  夏沫浅语  阅读(132)  评论(0编辑  收藏  举报