共计 4062 个字符,预计需要花费 11 分钟才能阅读完成。
我们在之前文章《ES6 class 与面向对象编程》中,说到了目前大部分框架和库,都采用了面向对象方式编程。那么具体是怎么样应用的呢?面向对象编程,最典型和最基础的作用就是封装,封装的好处就是代码的能够复用,模块化,进行项目和文件的组织。
今天我们就来看看 ES6class、模块化在一个被前端人员广泛使用的库 -vue 中,是怎么应用的。
在说 vue 模块化之前,我们先说说实现模块化的发展历程,这样才能不仅仅知其然,更知其所以然。
不然你看到 vue 的一个用法,你看到的只是这个用法,至于为什么是这样做,而不是其他方式,就不清楚了。这也是很多一看就懂,一写就卡的原因。
因为你学到的仅仅是这个例子,没办法迁移到自己的项目中。我们从头捋一捋:
js 模块化历史
很久很久以前,我们写代码是酱紫的,
<script src="a.js"></script>
<script src="b.js"></script>
<script src="c.js"></script>
但是这样写容易出一个问题,也就是变量名冲突,比如 a.js 是一个人写的,而 b.js 是另外一个人写的,两个人用了同样一个变量
var a = 12;
var a = 5;
这样就会出现变量覆盖的问题,当然我这里不想提听起来高大上的名字,什么全局变量污染。说的就是这点事儿。
针对这个问题,最原始最古老的 IIFE 来了,这是比较简单的创建 JS 模块的方法了。
//a.js
(function(){var a = 12;})();
//b.js
(function(){var a = 12;})();
这种方式在以前的各种库里面应用很多,比如大名鼎鼎的 jquery:
(function( window, undefined) {})(window);
但是这种模块化方式有一个缺点,不能解决依赖问题。
比如 b.js 里面的一个值,必须是 a.js 里面一个值计算完之后给 b.js,这样才能有正确的结果,显然,IIFE(匿名函数自执行)方式没办法解决。
好吧,我用一句大家听起来可能不太懂的话来显示一下我的专业性:
它只是把变量和方法都封装在本身作用域内的一种普通模式。其存在的缺点就是没有帮我们处理依赖。
说的就是上面的事儿。
然后 AMD 来了,别误会,不是 CPU,是模块化方式,AMD (异步模块依赖) : 其中代表就是 Require.js。它很受欢迎,它可以给模块注入依赖,还允许动态地加载 JS 块。
如下:
define(‘myModule’, [‘dep1’,‘dep2’], function (dep1, dep2){
// JavaScript chunk, with a potential deferred loading
return {hello: () => console.log(‘hello from myModule’)};
});
// anywhere else
require([‘myModule’], function (myModule) {myModule.hello() // display‘hello form myModule’});
有人说我看不懂这个代码,啥意思啊?
不用看懂,因为我们不用它,它的缺点就是:
代码复杂冗长。
显然对于我们这些脑子里只能装下 01 和美女的程序员来说,没有放它的地儿。
不过程序员还是喜欢耍酷的,这不,另外一种模块化方式流行了,CMD, 好吧,它跟我们的命令行没有半毛钱关系。
我就纳闷那些起名字的人了,成功的撞车了所有容易误会的名字。故意的吧?
Common Module Definition,简称 CMD, 很多人可能会问 AMD 和 CMD 的区别,知道了区别也没用。
对于 AMD 和 CMD 两种模式,你就把它们当成你的前前女友和前女友。曾经确实存在过,确实爱过,但是你前前女友和你前女友的区别,你没事是不会拿出来说的,对你找现任女友也没什么帮助(相反说多了会起反作用)。
当然了,还有一个模块化方式,Commonjs,这个模式广泛应用在 Nodejs 中,至于 nodejs 你懂的,披着 js 外衣的后台语言,哼哼,我们不用理它。
ok,说了这么多旧事,听了一堆乱七八糟的模块化,js 模块化的情史乱七八糟。JavaScript 标准化组织一琢磨,JavaScript 也老大不小了,得搞个官方的模块化的东西啊,不能老这么乱七八糟的悬着啊。
于是 js 被官宣了一个模块化方式 -ES6 模块化。
ES6 模块化
好,我们就看看这个正牌女友,官宣有什么优点:
1 每一个模块只加载一次,每一个 JS 只执行一次,如果下次再去加载同目录下同文件,直接从内存中读取。一个模块就是一个单例,或者说就是一个对象;
2 每一个模块内声明的变量都是局部变量,不会污染全局作用域;
3 模块内部的变量或者函数可以通过 export 导出;
4 一个模块可以导入别的模块;
5 能够实现异步和按需加载;
6 官方出台设定标准,不在需要出框架或者 hack 的方式解决该问题,该项已经作为标准要求各浏览器实现。
所以,从以上 6 点,我们可以看出来 ES6 模块化才是根儿正苗红的模块化接班人,重点是 ES6 官方模块化标准,虽然现在浏览器全部实现该标准尚无时日,但是肯定是未来趋势。
好,我们看看怎么用。
首先,我们先来一个入口文件 main.js
import numA from './a';
import {strB} from './b';
console.log(numA, strB);
接着,a.js
import {bNum} from './c';
export default {
strA: 'aa',
numA: bNum + 1
};
然后,b.js
import {strA} from './a';
export const strB = strA + 'bb';
最后,c.js
export const bNum = 0;
解释一下,就是 定义导出,然后倒入。这里注意两点就 OK 了,
1. 如果 导出的时候是 export default, 那么引入的时候
import fdasfas from './a';
名字随便起,而且不用加 {}
2. 如果导出的时候有名字,那么必须引入必须有名字,并且跟导出的名字一致,而且必须有 {}。
如导出,
export const strB = strA + 'bb';
那么倒入就必须:
import {strB} from './b';
记住这么多就 OK 了,为什么这么说呢?
其实 vue 的模块化里面,就是这点东西。
ES6 模块化在 vue 中的应用。
直接打开入口文件 main.js,我们会发现这样的代码:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
import VueMaterial from 'vue-material'
import 'vue-material/dist/vue-material.css'
import VueAwesomeSwiper from 'vue-awesome-swiper'
Vue.use(VueAwesomeSwiper)
Vue.use(VueMaterial)
Vue.material.registerTheme({
default: {
primary: {
color: 'red',
hue: 700
}
}
})
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: {App}
})
我们一看开头,是不是很熟悉?
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
import VueMaterial from 'vue-material'
import 'vue-material/dist/vue-material.css'
import VueAwesomeSwiper from 'vue-awesome-swiper'
顺藤摸瓜,我们看看 router 的导出:
export default new Router({//xxxxx})
是不是我们才讲过的东西?简单吧,另外我们再看看 main.js:
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: {App}
})
看见 new 关键字,我们第一反应就是 class,顺藤摸瓜。
class Vue extends V.Vue {}
export = Vue;
你会发现这么一句话,是不是很熟悉?但是我要说,这个代码不是 JavaScript 代码,而是 typescript。
从这个例子你就能体会到两件事:
1. 学会了面向对象和模块化,你就能看懂 vue 的代码组织方式和实现,可以尝试看 vue 源码了。
2. 忽然一不小心你居然学会了 typescript 的语法。
有没有一种本来打算出去打个酱油,却突然遇到了你女神,而且还发现她目前依然单身的感觉?
是不是想把 vue 源码看个遍,掌握那些你认为大牛才能掌握的技能?还犹豫啥?搞起吧。
总结:
总结一下,通过本节课的学习,我们学会了:
1. 我们了解了 js 模块化的历史,知道了为什么模块化会发展成现在的样子,这时候你应该体会到了技术为解决问题服务,怎么一步步解决问题的,而不是凭空产生新技术,新解决方案。这个对大家以后学习和融汇贯通都很重要,多问一个为什么。
2. 学会了 ES6 的模块化用法,就相当于打开了看懂各种框架的大门,以后大家要多学学模块化代码的组织和实现方式,为实际工作项目中的应用做好铺垫。
3. 看了一下 ES6 的模块化方式在 vue 中的使用,同时也看了一下 class 的应用,为大家看懂 vue 源码打下了基础。