js基础模块设计(代码片段)

wgchen~ wgchen~     2022-12-01     111

关键词:

阅读目录

模块设计

使用分析

项目变大时需要把不同的业务分割成多个文件,这就是模块的思想。模块是比对象与函数更大的单元,使用模块组织程序便于维护与扩展。

生产环境中一般使用打包工具如 webpack 构建,他提供更多的功能。但学习完本章节后会再学习打包工具会变得简单。

  • 模块就是一个独立的文件,里面是函数或者类库
  • 虽然JS没有命名空间的概念,使用模块可以解决全局变量冲突
  • 模块需要隐藏内部实现,只对外开发接口
  • 模块可以避免滥用全局变量,造成代码不可控
  • 模块可以被不同的应用使用,提高编码效率

实现原理

在过去JS不支持模块时我们使用 AMD/CMD(浏览器端使用)、CommonJS(Node.js使用)、UMD(两者都支持)等形式定义模块。

AMD代表性的是 require.js,CMD 代表是淘宝的 seaJS 框架。

下面通过定义一个类似 require.js 的 AMD 模块管理引擎,来体验模块的工作原理。

let module = (function() 
  //模块列表集合
  const moduleLists = ;
  function define(name, modules, action) 
    modules.map((m, i) => 
      modules[i] = moduleLists[m];
    );
    //执行并保存模块
    moduleLists[name] = action.apply(null, modules);
  

  return  define ;
)(); // hd module show

//声明模块不依赖其它模块
module.define("hd", [], function() 
  return 
    show() 
      console.log("hd module show");
    
  ;
);

//声明模块时依赖其它模块
module.define("xj", ["hd"], function(hd) 
  hd.show();
);

基础知识

标签使用

在浏览器中使用以下语法靠之脚本做为模块使用,这样就可以在里面使用模块的代码了。

在 html 文件中导入模块,需要定义属性type="module"

<script type="module"></script>

模块路径

在浏览器中引用模块必须添加路径如 ./,但在打包工具如 webpack 中则不需要,因为他们有自己的存放方式。

测试的 hd.js 的模块内容如下

export let hd = 
    name: "hs.js_file_name:wgchen"
;

下面没有指定路径将发生错误

<script type="module">
  import  hd  from "hd.js";
</script>

正确使用需要添加上路径

<script type="module">
  import  hd  from "./hd.js";
</script>


解决办法
在本地搭建一个server,通过url地址访问测试文件。

延迟解析

模块总是会在所有 html 解析后才执行,下面的模块代码可以看到后加载的 button 按钮元素。

  • 建议为用户提供加载动画提示,当模块运行时再去掉动画
<body>

  <script type="module">
    console.log(document.querySelector("button")); //Button
  </script>
  <script>
    console.log(document.querySelector("button")); //null
  </script>

  <button>wgchen_button</button>

</body>

模块默认运行在严格模式

模块默认运行在严格模式,以下代码没有使用声明语句将报错

<script type="module">
  hd = "wgchen"; // hd is not defined
</script>

下面的 this 也会是 undefined

<script>
  console.log(this); //Window
</script>

<script type="module">
  console.log(this); //undefiend
</script>

模块都有独立的顶级作用域

模块都有独立的顶级作用域,下面的模块不能互相访问

<script type="module">
  let hd = "wgchen.blog";
</script>

<script type="module">
  alert(hd); // Error:hd is not defined
</script>

单独文件作用域也是独立的,下面的模块 1.2.js 不能访问模块 1.1.js 中的数据

<script type="module" src="1.1.js"></script>
<script type="module" src="1.2.js"></script>

文件内容如下
# 1.1.js
let hd = "wgchen";

# 1.2.js
console.log(hd)


预解析

模块在导入时只执行一次解析,之后的导入不会再执行模块代码,而使用第一次解析结果,并共享数据。

  • 可以在首次导入时完成一些初始化工作
  • 如果模块内有后台请求,也只执行一次即可

引入多入 hd.js 脚本时只执行一次

<script type="module" src="./hd.js"></script>
<script type="module" src="./hd.js"></script>

#hd.js内容如下
console.log("wgchen");

在开发服务器模式下这样也可以访问到

<script type="module" src="hd.js"></script>
<script type="module" src="hd.js"></script>

下面在导入多次 hd.js 时只解析一次


导入导出

ES6使用基于文件的模块,即一个文件一个模块。

  • 使用 export 将开发的接口导出
  • 使用 import 导入模块接口
  • 使用 * 可以导入全部模块接口
  • 导出是以引用方式导出,无论是标量还是对象,即模块内部变量发生变化将影响已经导入的变量

导出模块

下面定义模块 modules/wgchen.js ,使用 export 导出模块接口,没有导出的变量都是模块私有的。

下面是对定义的 hd.js 模块,分别导出内容

export const site = "wgchen";

export const func = function() 
  return "is a module function";
;

export class User 
  show() 
    console.log("user.show");
  

下面定义了 hd.js 模块,并使用指量导出

const site = "wgchen";

const func = function() 
  return "is a module function";
;

class User 
  show() 
    console.log("user.show");
  

export  site, func, User ;

具名导入

下面导入上面定义的 hd.js 模块,分别导入模块导出的内容

<script type="module">
  import  User, site, func  from "./hd.js";
  console.log(site);
  console.log(User);
</script>



像下面这样在 中导入是错误的,模块默认是在顶层静态导入,这是为了分析使用的模块方便打包

if (true) 
  import  site, func  from "./hd.js"; // Error

批量导入

如果要导入的内容比较多,可以使用 * 来批量导入。

<script type="module">
  import * as api from "./hd.js";
  console.log(api.site);
  console.log(api.User);
</script>

导入建议

因为以下几点,我们更建议使用明确导入方式

  • 使用 webpack 构建工具时,没有导入的功能会删除节省文件大小
  • 可以更清晰知道都使用了其他模块的哪些功能

别名使用

导入别名

可以为导入的模块重新命名,下面是为了测试定义的 hd.js 模块内容。

  • 有些导出的模块命名过长,起别名可以理简洁
  • 本模块与导入模块重名时,可以通过起别名防止错误
const site = "wgchen";

const func = function() 
  return "is a module function";
;

class User 
  show() 
    console.log("user.show");
  


export  site, func, User ;

模块导入使用 as 对接口重命名,本模块中已经存在 func 变量,需要对导入的模块重命名防止重名错误。

<script type="module">
  import  User as user, func as action, site as name  from "./hd.js";
  let func = "wgchen";
  console.log(name);
  console.log(user);
  console.log(action);
</script>

导出别名

模块可以对导出给外部的功能起别名,下面是 hd.js 模块对导出给外部的模块功能起了别名

const site = "wgchen";
const func = function() 
  console.log("is a module function");
;
class User 
  show() 
    console.log("user.show");
  

export  site, func as action, User as user ;

这时就要使用新的别名导入了

<script type="module">
  import  user, action  from "./hd.js";
  action();
</script>

默认导出

很多时候模块只是一个类,也就是说只需要导入一个内容,可以使用默认导入。

使用 default 定义默认导出的接口,导入时不需要使用

  • 可以为默认导出自定义别名
  • 只能有一个默认导出
  • 默认导出可以没有命名

单一导出

下面是 hd.js 模块内容,默认只导出一个类。并且没有对类命名,这是可以的

export default class 
  static show() 
    console.log("User.method");
  

从程序来讲如果将一个导出命名为 default 也算默认导出

class User 
  static show() 
    console.log("User.method");
  

export  User as default ;

导入时就不需要使用 来导入了

<script type="module">
  import User from "./hd.js";
  User.show();
</script>

默认导出的功能可以使用任意变量接收

<script type="module">
  import hd from "./hd.js";
  hd.show();
</script>

混合导出

模块可以存在默认导出与命名导出。

使用 export default 导出默认接口,使用 export 导入普通接口

const site = "wgchen";
const func = function() 
  console.log("is a module function");
;
export default class 
  static show() 
    console.log("user.show");
  

export  site, func ;

也可以使用以下方式导出模块

const site = "wgchen";
const func = function() 
  console.log("is a module function");
;
class User 
  static show() 
    console.log("user.show");
  

export  site, func, User as default ;

导入默认接口时不需要使用 ,普通接口还用 导入

<script type="module">
	//可以将 hd 替换为任何变量
  import hd from "./hd.js";
  import  site  from "./hd.js";
  console.log(site);
  hd.show();
</script>

可以使用一条语句导入默认接口与常规接口

import show,  name  from "/modules/wgchen.js";

也可以使用别名导入默认导出

import  site, default as hd  from "./hd.js";
console.log(site);
hd.show();

如果是批量导入时,使用 default 获得默认导出

<script type="module">
  import * as api from "./hd.js";
  console.log(api.site);
  api.default.show();
</script>

使用建议

对于默认导出和命名导出有以下建议

  • 不建议使用默认导出,会让开发者导入时随意命名
import hd from "./hd.js";
import xj from "./hd.js";
  • 如果使用默认导入最好以模块的文件名有关联,会使用代码更易阅读
import hd from "./hd.js";

导出合并

解决问题

可以将导入的模块重新导出使用,比如项目模块比较多如下所示,这时可以将所有模块合并到一个入口文件中。

这样只需要使用一个模块入口文件,而不用关注多个模块文件

|--hd.js
|--wgchen.js
...

实际使用

下面是 hd.js 模块内容

const site = "wgchen";
const func = function() 
  console.log("is a module function");
;
export  site, func ;

下面是 wgchen.js 模块内容

export default class 
  static get() 
    console.log("wgchen.js.get");
  

下面是 index.js 模块内容,使用 * 会将默认模块以 default 导出

export * as hd from "./hd.js";

// 默认模块需要单独导出
export  default as wgchen  from "./wgchen.js";

// 以下方式导出默认模块是错误的
// export houdunren from "./wgchen.js";

使用方法如下

<script type="module">
  import * as api from "./index.js";
  console.log(api);
  api.wgchen.get();
  console.log(api.hd.site);
</script>

动态加载

使用 import 必须在顶层静态导入模块,而使用 import() 函数可以动态导入模块,它返回一个 promise 对象。

静态导入

使用 import 顶层静态导入,像下面这样在 中导入是错误的,这是为了分析使用的模块方便打包,所以系统禁止这种行为

if (true) 
  import  site, func  from "./hd.js"; // Error

动态使用

测试用的 hd.js 模块内容如下

const site = "wgchen";
const func = function() 
  console.log("is a module function");
;
export  site, func ;

使用 import() 函数可以动态导入,实现按需加载

<script>
  if (true) 
    let hd = import("./hd.js").then(module => 
      console.log(module.site);
    );
  
</script>

下面是在点击事件发生后按需要加载模块

<button>wgchen</button>
<script>
  document.querySelector("button").addEventListener("click", () => 
    let hd = import("./hd.js").then(module => 
      console.log(module.site);
    );
  );
</script>



因为是返回的对象可以使用解构语法

<button>wgchen</button>
<script>
  document.querySelector("button").addEventListener("click", () => 
    let hd = import("./hd.js").then(( site, func ) => 
      console.log(site);
    );
  );
</script>

指令总结

<

alpha冲刺—冲刺计划&代码规范(代码片段)

...——用户注册、用户登录、查看用户信息、用户注销项目基础功能模块接口——新建项目任务,查看项目,查看项目成员,添加/移除项目管理员等项目任务功能模块接口——查看项目任务接口文档撰写3、服务器部署4、杂项文档... 查看详情

px4模块设计之十七:modulebase模块(代码片段)

...数4.总结5.参考资料1.ModuleBase模块介绍ModuleBase模块是一个基础类,主要完成各个模块需要的基础功能,比如&#x 查看详情

js设计模式(代码片段)

...场合单例模式Singleton原型模式Prototype构造器模式Constructor模块模式Module揭示模块模式RevealingModule观察者模式Observer发布订阅模式Pub 查看详情

px4模块设计之四十一:i2c/spibusinstance基础知识(代码片段)

PX4模块设计之四十一:I2C/SPIBusInstance基础知识1.基础知识2.基础类和定义2.1ListNode类2.2List类2.3BusCLIArguments类2.4BusInstanceIterator类2.5I2CSPIInstance类2.6I2CSPIDriverBase类2.7I2CSPIDriver类2.8I2C/SPI总线选项3.总结4.参考资料1.基础知 查看详情

02commonjs规范基础使用详解(代码片段)

Commonjs规范1.1commonjs规范说明每一个js文件就是一个模块,文章中我说的模块可以等价为一个js文件node应用由模块组成,采用的commonjs模块规范。每一个js文件就是一个模块,拥有自己独立的作用域,变量,以及方法等,对其他的... 查看详情

vue框架之基础(代码片段)

介绍vue.js是用来构建web应用接口的一个库技术上,Vue.js重点集中在MVVM模式的ViewModel层,它连接视图和数据绑定模型通过两种方式。实际的DOM操作和输出格式被抽象的方式到指令(Directives)和过滤器(Filters)在哲学领域内,尽量... 查看详情

node.js基础(代码片段)

...hromeV8引擎的JavaScript运行时环境。接下来学习一下node.js的基础。一、 查看详情

03amd规范的基础使用详解(代码片段)

AMD模块规范1.1AMD规范说明AMD规范专门用来实现浏览器端的模块化,并且模块的加载是异步的;引入一个第三方的require.js脚本用来解析AMD规范编写的模块1.2基本语法使用define用来暴露模块,使用require用来引入模块1.21暴露模块(1... 查看详情

蓝桥杯单片机设计与开发_基础模块_ds18b20(代码片段)

一、前言从今天开始,笔者将向大家逐一讲解蓝桥杯的大部分竞赛模块,笔者将基于上一篇文章(蓝桥杯单片机设计与开发_标准模板)中讲解的标准模板编写程序。按照顺序(DS18B20、DS1302、PCF8591、AT24C02、PWM... 查看详情

node基础1--初识node.js与内置模块(代码片段)

...法调用DOM和BOM等浏览器内置API。Node.js的学习计划JavaScript基础语法+Node.js内置API模块(fs、path、http等)+第三方API模块( 查看详情

node基础2--模块化(代码片段)

模块化1.模块化的基本概念1.1什么是模块化1.2把代码进行模块化拆分的好处1.3模块化规范1.4模块化规范的好处Node.js中模块化2.1Node.js中模块的分类2.2加载模块2.3Node.js中的模块作用域2.4向外共享模块作用域中的成员2.5Node.js中的模块... 查看详情

销售系统项目业务分析和java中使用邮箱(代码片段)

项目一般大致可分为三个模块,我们以销售系统为例分为基础模块进货模块财务模块三个基础模块分为:权限模块产品模块和基础代码,基础模块的设计十分重要会影响到整个项目,代码较为简单核心模块:以销售系统为例核心... 查看详情

一短文带你快速入门node.js基础及内置模块(代码片段)

1.什么是Node.jsNode.js是一个开源与跨平台的JavaScript运行时环境。与2009年发布。它是在浏览器外运行,它是一个事件驱动异步I/O单进程的服务端JS环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常... 查看详情

node.js文件系统操作(代码片段)

文章目录文件系统基础fs模块同步、异步文件操作文件路径文件模式文件与目录基本操作文件基本操作目录的基本操作文件系统高级操作流接口文件遍历和监视文件遍历文件监视JSON格式文件操作文件系统基础fs模块fs模块提供一... 查看详情

商城系统中商品模块数据库设计的一些思考(代码片段)

...设计的一些思考一般我们要做的商城系统比较庞大,最最基础的就是商品表的设计,一件商品又牵扯到商品的属性、规格、分类,每种规格又有不同的库存和价格,所以数据库设计时需要均衡考虑,一个是方便拓展,另一个是方... 查看详情

android模块化设计之组件开发规范(代码片段)

最近一直在做基础建设方面的工作,面对这三十多个完全没有规范可言的组件,气的我直接打了一套闪电五连鞭,但打工还得继续,于是想对这些组件建立一套规范,来降低够用、使用、维护以及扯皮成本ÿ... 查看详情

vue组件基础(组件的嵌套vuecomponent)(代码片段)

欢迎学习交流!!!持续更新中…文章目录组件化编程1.模块与组件、模块化与组件化2.非单文件组件3.组件的嵌套4.关于VueComponent一个重要的内置关系5.单文件组件.vue文件的组成(3部分)基本使用组件化编程1.... 查看详情

青训营node.js基础-特点-模块化commonjs&esm-npm包管理(代码片段)

文章目录起步安装与运行版本管理特点异步I/O单线程多进程的浏览器跨平台应用场景模块化机制CommonJS规范机制加载方式npm包查找原则npm缓存其他模块化规范ESModules(ESM)CommonJSVSESMCommonJS:值的**拷贝**ESM:值的**引用**常用... 查看详情

免责声明:如内容涉及版权或违规等问题,请在尽快内联系我们pp114#vip.qq.com,我们将在第一时间删除内容。

表达式 说明
export function show() 导出函数
export const name='wgchen' 导出变量
export class User 导出类
export default show 默认导出
const name = 'wgchen'
export name
导出已经存在变量
export name as hd_name 别名导出
import defaultVar from 'wgchen.js' 导入默认导出
import name,show from 'a.j' 导入命名导出
Import name as hdName,show from 'wgchen.js'