前端模块化

前端模块化

这里复习了一个知识点,就是在一个html页面中有两个相同的事件监听函数时,后面那个会覆盖掉前面那个,就像是变量重新赋值一样。

<script src="js/main.js"></script>
<script src="js/xiaoming.js"></script>
<script src="js/xiaohon.js"></script>
window.onload = function(){
  var name = '小明';
  console.log(name);
};
window.onload = function(){
  var name = '小红';
  console.log(name);
};

最终控制台打印的是小红

一、为什么前端需要模块化开发?

我们首先需要知道的是,在HTML文件中引入js文件,就相当于是将这个js文件拷贝到了引入的标签的地方。

<script src="js/main.js"></script>
<script src="js/xiaoming.js"></script>
<script src="js/xiaohon.js"></script>

就相当于这样

<script src="js/main.js"></script>
  var name = '小明';
  console.log(name);
  console.log(name);
  var name = '小红';
  console.log(name);

你会发现若是团队开发的时候很容易就出现了全局变量命名重复的问题,比如说这个案例,小明原来定义name是自己的名字,然后小红也定义了一个name,并且改成了自己的名字。后来小明在做一些操作的时候,使用到这个name,结果完全没有达到自己想要的效果,这就尴尬了。

在js中甚至你变量命名重复都不会报错,只是在编译器中有个warning而已

<script src="js/main.js"></script>
<script src="js/xiaoming.js"></script>
<script src="js/xiaohon.js"></script>
<script src="js/xiaoming1.js"></script>
if("小明" === name){
  console.log("小明是天才,哈哈哈哈");
}

由于name被小红改成自己的名字了,小明这段话不可能打印的出来了。所以,全局变量命名重复是个大问题。由于es5中只有全局作用域函数作用域,所以这个问题的解决方式就只能是使用匿名函数

(function(){
  var name = '小明';
  console.log(name);
})();

就像是这样,但是这又会出现问题了,就是小明写的东西就不能重复利用了,就像是时间格式化的函数toLocalDate这样常用的函数,小明在这个闭包中写了,那到了别的地方想用了,却用不了,难道复制粘贴一份?那成本太高了。

所以,上面不是出现全局变量命名冲突就是会出现代码无法复用的问题,这就是为什么需要使用模块化的概念,就像是java中,你定义了一个工具类,那之后就不需要再重复定义了,直接import就可以了。

二、自己实现模块化

闭包内部可以创建一个对象,将需要在别的地方使用的东西给存入这个对象中,然后在匿名函数外面创建一个模块对象去接收这个导出的对象,由于模块对象是全局作用域的,那么在别的地方就可以使用了。

var modelA = (function(){
  var obj = {};
  var name = '小明';
  console.log(name);
  obj.toLocalDate = function (){
    var date = new Date();
    return date.getFullYear()+"/"+(date.getMonth()+1)+"/"+date.getDate()+"  "+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
  };
  console.log(obj.toLocalDate());
  obj.name = name;
  return obj;
})();
if("小明" === modelA.name){
  console.log("小明是天才,哈哈哈哈");
}
console.log(modelA.toLocalDate());

这时候在别的地方就能使用之前写的东西了,这就是模块化思想,解决了全局变量命名重复代码复用

三、使用定义好的模块化规范

​ 前端发展到了现在,已经有了很多模块化的规范了,之后使用模块化都是按照别人的规范来进行模块化开发。现在常见的模块化规范有:CommonJS 、AMD、CMD、和ES6的Modules,其中CommonJS和ES6的模块化比较常用。其实,不管规范怎么定义的,他们都有两个核心的点是不变的,就是导入和导出,就像是我们自己实现的模块化一样,你得先把一个闭包的东西给导出,然后才能在别的地方导入使用吧。下面就来学习一下CommonJS和ES6的模块化的导入和导出语法。

1. CommonJS,大名鼎鼎的Node.js就是实现了CommonJS的规范

导出

var name = '小明';
console.log(name);
function toLocalDate(){
  var date = new Date();
  return date.getFullYear()+"/"+(date.getMonth()+1)+"/"+date.getDate()+"  "+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
}
module.exports = {
    //对象字面量的增强写法
    name,
    toLocalDate
};

你会发现,这里没有使用闭包,因为在模块化规范中,一个JS就是一个模块了,它会有自己的作用域。

导入

//CommonJS的导入方法
//{name,toLocalDate}这叫做对象的解构
//等同于 分别定义了两个变量name,toLocalDate
//然后把require返回的对象中的name和toLocalDate分别赋值给他们
let {name,toLocalDate} = require('./xiaoming.js');
if("小明" === name){
  console.log("小明是天才,哈哈哈哈");
}
console.log(toLocalDate());

CommonJS直接肯定是使用不了的,因为需要有实现了它规范的东西给你的代码做支撑,不然连exportsrequire关键字都找不到。

2. ES6的模块化

使用了模块化之后,每一个JS文件就是一个独立的模块,即使不使用闭包也不会出现全局变量命名冲突的问题

<script src="js/xiaoming.js" type="module"></script>
<script src="js/xiaohon.js" type="module"></script>
<script src="js/xiaoming1.js" type="module"></script>

这样就是声明了这些JS文件是通过模块化的思想开发的。

xiaoming.js

var name = '小明';
console.log(name);
function toLocalDate(){
  var date = new Date();
  return date.getFullYear()+"/"+(date.getMonth()+1)+"/"+date.getDate()+"  "+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
}

xiaoming1.js

console.log(toLocalDate());

由于使用了模块化开发的规范,所以在别的地方使用就自己报错了,因为在这个模块中还没有定义,很明显命名冲突的问题解决了。

Uncaught ReferenceError: toLocalDate is not defined

ES模块化的导入和导出

导出

//ES6导出
var name = '小明';
//1.直接导出
export var flag = true;
console.log(name);
function toLocalDate(){
  var date = new Date();
  return date.getFullYear()+"/"+(date.getMonth()+1)+"/"+date.getDate()+"  "+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
}
//以前定义类也是使用function,ES6后直接使用class定义类了,还能定义构造函数
export class Person{
  constructor(name) {
    this.name = name;
  }
  sayName(){
    console.log(this.name);
  }
}
//2.某些时候,我们只是导出一个功能,而且想要由使用者来为他命名,那就得使用export default来进行导出,
//每个模块中只能有一个export default,若是有多个的话,导入的时候就不知道哪个是哪个了,
// 因为都是没有名字的
// export default function (person) {
//   person.sayName();
// }
//注意:需要先定义这个变量才能export default,不然会报错的,不能写在一行
const height = 1.88;
export default height;
//3.导出一个对象
export {
  name,toLocalDate
}

导出有三种语法,一种是定义的时候直接在前面export导出,或者在下面export导出一个对象,还可以export default,让别人能够在导入的时候自定义名字,不过每个模块中只能export default一个东西,不然别人导入的时候就不知道导入的是什么了。

导入

//ES6导入第一种方式:import {} from "path";
//若是导入的东西很多的话,这样写就很麻烦,而且
// 导入的东西还可能和自己定义的东西重名又冲突了,
// 所以还有一种方式,
//import * as 自定义对象名 from "path";就是把
// path这个文件中所有导出的东西放到你自定义的对象中
import {name,toLocalDate,flag,Person} from "./xiaoming.js";
if("小明" === name){
  console.log("小明是天才,哈哈哈哈");
}
console.log(toLocalDate());
if(flag){
  console.log("小明是傻子,哈哈哈哈");
}
let xiaoming = new Person("小明");
xiaoming.sayName();
// import sayName from "./xiaoming.js";
// sayName(xiaoming);
import h from "./xiaoming.js";
console.log(h);
//*******************************************************
import  * as xmModel from "./xiaoming.js";
if("小明" === xmModel.name){
  console.log("小明是天才,哈哈哈哈");
}
console.log(xmModel.toLocalDate());
if(flag){
  console.log("小明是傻子,哈哈哈哈");
}
let xiaoming1 = new xmModel.Person("小明");
xiaoming1.sayName();
//export default就是将这个变量或者是函数什么的放到xmModel里面的一个default变量中
console.log(xmModel.default);

在style标签中导入文件的时候语法这样

@import + 文件路径

在使用路由懒加载的时候这样导入

import + (+文件路径+),这个路径要使用括号包起来

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容

  • 前言在 JavaScript 发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今 CPU、浏览器性能得到了...
    前端一菜鸟阅读 833评论 0 9
  • 前言 在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大...
    Aniugel阅读 1,470评论 0 0
  • 1. 前言 现在的前端开发, 通常是一个单页面应用,每一个视图通过异步的方式加载,这导致页面初始化和使用过程中会加...
    majun00阅读 728评论 0 2
  • 还没进病房,梅子出来迎我,紧张兮兮地拉着我说,二姐,你劝劝大姐,她来开个刀,好像来旅行一样,拉着个行李箱,化妆包,...
    羲予阅读 1,291评论 5 35
  • 1.添加依赖 2.增加注解 3.参数配置示例 4.http://localhost:8080/swagger-ui...
    一块没梦想的海绵宝宝阅读 2,385评论 0 0