模块化概念
- 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起。
- 块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信。
为什么使用模块化
- 在实际的开发过程中,经常会遇到变量、函数、对象等名字的冲突,这样就容易造成冲突,还会造成全局变量被污染,特别是合作开发时,大家的命名规范可能类似,很有可能出现重名,所以冲突时还要排查。
程序或者网站复杂时需要写很多代码,而且还要引入很多类库,这样稍微不注意就容易造成文件依赖混乱。
- 在没有模块化之前,一个文件中可能需要引入很多的js文件和包,比如jQuery、Bootstrap、swiper等等,所以上来需要先使用link导入很多包。
补充:引用js文件时的变量覆盖
现在有两个js文件aaa.js和bbb.js文件
aaa.js:
var name="张三"
bbb.js:
var name="李四"
新建html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/aaa.js"></script>
<script src="js/bbb.js"></script>
<script>
alert(name);
</script>
</head>
<body>
</body>
</html>
- 第8、9两行分别引用aaa.js和bbb.js
- 第11行打印name变量
问题:弹窗的内容是什么?
测试页面:
可以发现是李四被打印出来了。
原因是因为引用js文件时,当有同一个变量名时,最后引用的会覆盖之前的,这就是变量覆盖,也造成了变量污染,因此需要模块化。
模块化的发展历程
- 在之前的javascript中是没有模块化概念的。如果要进行模块化操作,需要引入第三方的类库。
- AMD/CMD(用于浏览器环境)、CommonJs(用于Node环境)
随着技术的发展,前后端分离,前端的业务变的越来越复杂化。直至ES6带来了模块化,才让javascript第一次支持了module(用于浏览器环境)
ES6的模块化的使用
- ES6的模块化分为导出(export)与导入(import)两个模块。
在ES6中每一个模块即是一个文件,在文件中定义的变量,函数,对象在外部是无法获取的。
- 如果希望外部可以读取模块当中的内容,就必须使用export来对其进行暴露(输出)。
- 如果在其他文件中想要获取暴露的内容,以import的形式将这个变量进行引入。
例如vue-cli创建的初始项目中,在views目录下的页面文件Home.vue:
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'Home',
components: {
HelloWorld
}
}
</script>
- 第10行使用imprt导入了components组件库的HelloWorld.vue组件
打开components组件库中对应的HelloWorld.vue文件:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
- 35-40行使用export导出自己,否则别人无法引用。
所以总结以上思路,当A模块调用B模块时,B模块首先要使用export导出,这样A模块才能使用import导入。
导入与导出(import/export)
首先在public文件夹中新建js目录,然后在js目录中新建aaa.js文件:
aaa.js:
var name="冒险岛"
var job="战士"
- 创建name和job变量
在public文件夹中新建demo.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var job="魔法师"
</script>
<script src="js/aaa.js"></script>
<script>
console.log(name,job)
</script>
</head>
<body>
</body>
</html>
- 第9行在html中创建job变量为魔法师
- 第11行使用src引入aaa.js文件
- 第13行打印name和job变量
测试页面:
可以发现第9行的job变量魔法师被覆盖了。
如果现在需要实现打印job为魔法师,同时打印name为冒险岛,怎么解决变量覆盖问题?
答案就是使用模块化来解决变量覆盖问题。
导出
- 任何需要被其他组件或者文件调用的内容都需要使用export导出
- 可以导出变量,函数,对象等等多种类型
- 在一个js文件中可以将通过计算后的结果使用export导出,供其他文件进行使用。
使用export将aaa.js中的name变量导出:
export var name="冒险岛"
export var job="战士"
export var fun=function(){
return "maple story"
}
导入
html页面导入引用js文件
在demo.html中使用import导入aaa.js中的变量和方法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="module">
import {name, job, fun} from "./js/aaa.js"
console.log(name);
console.log(job);
console.log(fun()); // 使用导入的方法需要添加括号
</script>
</head>
<body>
123
</body>
</html>
- 第9行使用import...from...(
{}
中添加需要导入的变量名和函数名)来导入文件中的变量
测试页面:
在aaa.js同级目录中新建bbb.js文件:
bbb.js:
var a=123;
var b=456;
var c=789;
export {c}
aaa.js:
import {c} from "./bbb.js"
export var name="冒险岛"
export var job="战士"
export var fun=function(){
return "maple story"
}
export var computed = c+123;
- 导入bbb.js中的c变量,然后新创建computed变量导出计算之后的值。
demo.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="module">
import {name, job, fun, computed} from "./js/aaa.js"
console.log(name);
console.log(job);
console.log(fun()); // 使用导入的方法需要添加括号
console.log(computed);
</script>
</head>
<body>
123
</body>
</html>
- 第13行打印computed变量
测试页面:
成功打印computed值,总结一下,aaa.js调用了bbb.js中的c变量,然后对c变量计算之后赋值给computed变量,然后export导出,再在demo.html中import导入并调用aaa.js中的computed变量。
注意
- 没有使用export导出的变量或者方法,是不能被其他组件import导入的
- 按需导入,只导入使用到的内容
当导入时from后面的模块没有路径,如下图所示,代表是从mode_modules目录下去寻找模块。
- 所以一般引用插件,直接在index.js中import插件名称即可自动去node_modules目录下寻找
此处评论已关闭