2

关于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操作的时候,或许可以采用以上做法。


lxcan
337 声望32 粉丝