单页——前端模块化
?个?够复杂的?程,需要尽量将功能解耦。什么叫解耦?简单来说,需要将不同的功能分开到不同的?件中,或不同的?录结构中,形成?个个模块,模块之间通过有限的接?交互,模块内部的数据变化对外部隐藏。
在 Node.js 上,这?点表现的?常不错。Node.js 实现了 CommonJS 规范,每个 JS ?件就是?个模块,模块中的所有数据对外隐藏,仅通过 Module.exports 暴露模块内的内容。于是,模块化开发在 Node.js 环境中已不成问题。
1. ?个 JavaScript ?件,即?个模块。
2. 模块中所有的数据,除?导出,否则都是私有数据,仅能在模块中访问。
3. 使? export 关键字导出模块。
4. 使? import 关键字导?模块,导?时使?解构表达式得到导出的数据,否则,将使?导出的默认
数据。
5. ?个模块可以有多个导出。
6. 导?的模块会被缓存。
7. 在??中加载??模块使? <script type="module" src="??模块">
一、模块导出
1、导出数据,定义一个变量,将要导出的数据赋值给变量,通过export导出
// 导出数据 export var color = "red"; export let name = "Nicholas"; export const magicNumber = 7;
2、导出函数,在函数前加上export导出
// 导出函数 export function sum(num1, num2) { return num1 + num2; }
3、导出类,在类class前加上export导出
// 导出类 export class Rectangle { constructor(length, width) { this.length = length; this.width = width; } }
4、也可将定义的私有函数导出,通过export对象导出
// 定义?个函数 function multiply(num1, num2) { return num1 * num2; } // 稍后将其导出 export { multiply };
以上方法最终能够得到的结果为:
{ color: "red", name: "Nicholas", magicNumber: 7, sum: function, Rectangle: class, multiply: function }
二、模块导?
import { color, name, multiply } from "./mymodule.js";
这是导入模块的基本形式。
也可使用通配符(*)导入模块中的所有东西:
import * as all from "./mymodule.js"; // all 可以是任意的名称 // 导?后,all 是?个对象,包含模块中导出的所有内容
注意,export 与 import 都有?个重要的限制,那就是它们必须被?在其他语句或表达式的外部。
if (flag) { export flag; // 语法错误 } function tryImport() { import flag from "./example.js"; // 语法错误 }
以上的导出导入方法就是错误的!
三、导?导出默认值
为了简化导?导出语法,还提供了?种导?导出的?式:默认值。使?这种?式导?导出会更加简单,但要注意的是,每个模块只能导出?个默认值。
export default function(num1, num2) { return num1 + num2; }
<script type="module" src="./app.js"></script>
在base文档中书写以下代码:
export default class { //登录页面的视图 constructor({ el }) { //element this.el = el; this.init(); } init() { this.render(); this.mounted(); this.handle(); } render() { //负责页面渲染 } mounted() { //负责挂载其他操作 } handle() { //负责事件监听的 } }
使用导出默认值的方式导出。
之后再主info.js中导入:
import Base from "./base.js";
之后就可以在info.js中使用继承了:
页面的渲染,事件监听都做好后就可以将其整体再次默认导出,在路由router文档中建立url接口,导入浏览器需要显示的info.js:
import info from "./view/info.js"; import addBooks from "./view/books/addBooks.js"; import updateBooks from "./view/books/updateBooks.js"; var routes = { ‘/info‘: { on: function () { new info({ el: "#root" }) }, ‘/addBooks‘: function () { new addBooks({ el: "#root" }) }, ‘/updateBooks‘: function () { new updateBooks({ el: "#root" }) } } }; var router = Router(routes); export default { init() { router.init(); //初始化路由 location.hash = location.hash || "/info"; //有锚点就不会回到第一个锚点 } };
在进行new的时候,最好使用与导出的标识符相同的单词,这样import会自动出现,避免书写麻烦,或错误导致无法联通。
总的来说,浏览器的模块化开发就是将页面渲染、事件监听进行包裹,整体的导出导入,达到我们一开始说的“形成?个个模块,模块之间通过有限的接?交互,模块内部的数据变化对外部隐藏。”,虽然前期的学习这种方式容易使人混乱,但是让我们的代码实现了工程化,每一个文档都有自己独立的目的,让我们的代码维护更加方便。