关于ES6 Module 的语法,详情可以查看阮一峰老师的《ECMAScript 6 入门》里面关于Module的章节
Module 的语法
本文主要讲下ES6 模块化与 .vue 组件的一个应用。
ES6 模块与 CommonJS 模块的差异
以下部分内容引用阮一峰老师的《ECMAScript 6 入门》这一章节ES6 模块与 CommonJS 模块的差异
开始之前,必须了解到,ES6 模块与 CommonJS 模块完全不同。
主要有两个差异。
- CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
第二个差异是因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
下面主要看下第一个差异
CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。看下这个模块文件module.js的例子。
// module.js
let count = 9;
function addCount() {
count++;
}
module.exports = {
count: count,
addCount: addCount,
};
上面代码输出内部变量count和改写这个变量的内部方法addCount。然后,在main.js里面加载这个模块。
// main.js
let mod = require('./module.js');
console.log(mod.count); // 9
mod.addCount();
console.log(mod.count); // 9
上面代码说明,module.js模块加载以后,它的内部变化就影响不到输出的mod.count了。这是因为mod.count是一个原始类型的值,会被缓存。除非写成一个函数,才能得到内部变动后的值。
// module.js
let count = 9;
function addCount() {
count++;
}
module.exports = {
get count() {
return count;
},
addCount: addCount,
};
上面代码中,输出的count属性实际上是一个取值器函数。现在再执行main.js,就可以正确读取内部变量count的变动了。
$ node main.js
9
10
ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。换句话说,ES6 的import有点像 Unix 系统的“符号连接”,原始值变了,import加载的值也会跟着变。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
上面的例子使用ES6 模块化写法:
// module.js
export let count = 9;
export function addCount() {
count++;
}
// main.js
import { count, addCount } from './module.js';
console.log(count); // 9
addCount();
console.log(count); // 10
上面代码说明,ES6 模块输入的变量count是活的,完全反应其所在模块module.js内部的变化。
export通过接口,输出的是同一个值。不同的脚本加载这个接口,得到的都是同样的实例。(一个模块就是一个实例,或者说就是一个对象)
// module.js
let count = 100;
export default {
add: function () {
count += 1;
},
show: function () {
console.log(count);
}
}
上面的脚本module.js,输出的是一个对象,包含了两个方法。不同的脚本加载这个模块,得到的都是同一个对象。
// a.js
import m from './module.js';
m.add();
// b.js
import m from './module.js';
m.show();
// main.js
import './a.js';
import './b.js';
现在执行main.js,输出的是101。
$ babel-node main.js
101
这就证明了a.js和b.js加载的都是同一个对象。
.vue组件应用举例
<template>
<div :id="chartId"></div>
</template>
<script>
let chartIdSeed = 1;
export default {
name: 'my-chart',
props: ['data'],
data() {
return {
chartId: '',
}
},
created() {
this.chartId = 'my-chart_' + chartIdSeed++;
},
mounted() {
this.$nextTick(() => {
let dom = document.getElementById(this.chartId);
// Do some dom manipulation...
});
}
}
</script>
以上代码,当你引入my-chart组件,并多次使用时,每次使用会生成不同的id。
当你的.vue组件需要有不同的id,要做一些dom操作的时候,或许可以采用以上做法。