• JS模块化


    JS模块化

    什么是模块化?

    将一个复杂的程序依据一定的规则(规范)封装成几个块(文件),并进行组合在一起。

    块的内部数据/实现是私有的,只是向外部暴露一些接口(方法)与外部其它模板通信。

    把所有的js代码写在一起,功能点不明确,耦合度不够,很难维护。

    模块化的优点
    1. 避免命名冲突,减少命名空间污染
    2. 更好的分离,按需加载
    3. 更高复用性
    4. 高可维护性
    页面引入加载script

    引入的过多,发的请求就会过多 依赖模糊 并且要注意引用的顺序 难以维护

    常见的模块化规范和工具

    CommonJS(通用模块化规范)
    规范
    说明
    • 每个文件都可以当作一个模块
    • 在服务器端:模块的加载时运行时同步加载的-->会发生阻塞
    • 在浏览器端:模块需要提前编译打包处理 
    实现
    服务器端实现

    基本语法

    暴露模块

    1. //value可以是任意的数据类型
    2. 1.module.exports = value
    3. 2.exports.xxx = value
    4. //暴露的模块到底是什么? 暴露的本质都是exports这个对象
    5. //原本exports就是空的对象

    引入模块

    1. require(xxx)
    2. 第三方模块 :xxx为模块名
    3. 自定义模块:xxx为模块文件路径

    下载第三方模块 npm install xx

    模块化编码 

    1. ##app.js
    2. //引入第三方库时要放到自定义库的上面
    3. let uniq = require('uniq')
    4. //将其他模块汇聚到主模块
    5. let module1 =require('./modules/module1')
    6. let module2 =require('./modules/module2')
    7. let module3 =require('./modules/module3')
    8. //如何使用
    9. module1.foo()
    10. module2()
    11. module3.bar()
    12. module3.foo()
    13. let result = uniq(module3.arr)
    14. console.log(result)
    15. ##module1.js
    16. //module.exports = value
    17. module.exports ={
    18. msg:'module1',
    19. foo(){
    20. console.log(this.msg);
    21. }
    22. }
    23. ##module2.js
    24. //暴露一个函数 module.exports =function(){}
    25. module.exports=function(){
    26. console.log('module2');
    27. }
    28. //再写一个的话 module1.exports对象会被覆盖
    29. ##module3.js
    30. //exports.xxx = value
    31. //用这种方式暴露就是无限的给对象添加属性
    32. exports.foo=function (){
    33. console.log('foo()module3');
    34. }
    35. exports.bar=function (){
    36. console.log('bar()module3');
    37. }
    38. exports.arr=[1,1,2,3,4,5,1]

     

    浏览器端实现
    1. |-js
    2. |-dist //打包生成文件的目录
    3. |-src //源码所在的目录
    4. |-module1.js
    5. |-module2.js
    6. |-module3.js
    7. |-app.js //应用主源文件
    8. |-index.html
    9. |-package.json
    10. {
    11. "name": "browserify-test",
    12. "version": "1.0.0"
    13. }
    1. ## module1.js
    2. module.exports = {
    3. foo() {
    4. console.log('moudle1 foo()')
    5. }
    6. }
    7. ## module2.js
    8. module.exports = function () {
    9. console.log('module2()')
    10. }
    11. ## module3.js
    12. exports.foo = function () {
    13. console.log('module3 foo()')
    14. }
    15. exports.bar = function () {
    16. console.log('module3 bar()')
    17. }
    18. ## app.js
    19. //引用模块
    20. let module1 = require('./module1')
    21. let module2 = require('./module2')
    22. let module3 = require('./module3')
    23. let uniq = require('uniq')
    24. //使用模块
    25. module1.foo()
    26. module2()
    27. module3.foo()
    28. module3.bar()
    29. console.log(uniq([1, 3, 1, 4, 3]))

     

    AMD(异步模块定义)
    规范
    说明

    专门用于浏览器端,模块的加载是异步的。

    基本语法

    定义暴露模块

    1. //定义没有依赖的模块
    2. define(function(){
    3. return 模块
    4. })
    5. //定义有依赖的模块
    6. //第一个参数必须是一个数组,数组里面放置的是依赖的模块 第二个参数是函数 函数要有形参
    7. define(['module1','module2'],function(m1,m2){
    8. return 模块
    9. })

    引入使用模块

    1. require(['module1','module2'],function(m1,m2){
    2. 使用m1/m2
    3. })
    实现
    非AMD实现

    1. ## dataService.js
    2. // 定义一个没有依赖的模块
    3. (function(window){
    4. let name='dataService.js';
    5. function getName(){
    6. return name
    7. }
    8. window.dataService={getName};
    9. })(window)
    10. ## alerter.js
    11. // 定义一个有依赖的模块
    12. (function(window,dataService){
    13. let msg='alerter.js'
    14. function showMsg(){
    15. console.log(msg,dataService.getName());
    16. }
    17. window.alerter={showMsg};
    18. })(window,dataService)
    19. ## app.js
    20. (function (alerter) {
    21. alerter.showMsg();
    22. })(alerter)
    23. ## test.html
    24. <script src="./js/dataService.js"></script> //由于alerter.js依赖于dataService,所以也要在引入alerter之前引入dataService.js文件
    25. <script src="./js/alerter.js"></script> //引入alerter.js文件
    26. <script src="./app.js"></script> //单独引入app.js找不到alerter文件
    AMD实现

    1. ##dataService.js
    2. // 定义没有依赖的模块
    3. define(function () {
    4. let msg = 'atguigu.com'
    5. function getMsg() {
    6. return msg
    7. }
    8. // 暴露模块
    9. return { getMsg }
    10. })
    11. ##alerter.js
    12. // 定义有依赖模块
    13. define(['dataService'], function (dataService) {
    14. let name = 'Tom2'
    15. function showMsg() {
    16. console.log(name, dataService.getMsg());
    17. }
    18. // 暴露模块
    19. return { showMsg }
    20. })
    21. ##main.js
    22. // 引入模块
    23. (function () {
    24. // 配置
    25. require.config({
    26. //映射: 模块标识名: 路径
    27. paths: {
    28. //自定义模块
    29. alerter: './modules/alerter',
    30. dataService: './modules/dataService',
    31. },
    32. })
    33. // 引入模块使用
    34. requirejs(['alerter'], function (alerter) {
    35. alerter.showMsg();
    36. })
    37. })()
    38. ##index.html
    39. <script data-main="js/main.js" src="js/libs/require.js"></script>
    40. ##先加载require.js文件,然后加载main.js

    CMD (简单了解即可)
    ES6(目前应用最广泛)

    ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性

    • 依赖模块需要编译打包处理;
    • 导出模块: export;
    • 引入模块: import;
    • 使用Babel将ES6编译为ES5代码;(有的浏览器不支持)
    • 使用Browserify编译打包js;(require语法)

    1.定义package.json文件

    1. {
    2. "name" : "es6-babel-browserify",
    3. "version" : "1.0.0"
    4. }

    2.安装 

    1. npm install babel-cli browserify -g
    2. npm install babel-preset-es2015 --save-dev

     3。定义.babelrc文件

    1. {
    2. "presets": ["es2015"]
    3. }

     4.编码

    1. ##js/src/module1.js
    2. // 暴露模块 分别暴露
    3. export function foo(){
    4. console.log('foo() module1');
    5. }
    6. export function bar(){
    7. console.log('bar() module1');
    8. }
    9. export let arr=[1,2,3,4,5]
    10. ## js/src/module2.js
    11. // 统一暴露
    12. function fun() {
    13. console.log('fun() module2');
    14. }
    15. function fun2() {
    16. console.log('fun2() module2');
    17. }
    18. export { fun, fun2 };
    19. ## js/src/module3.js
    20. //默认暴露 可以暴露任意数据类型,暴露什么数据类型,暴露什么数据接收到的就是什么数据
    21. // export default value
    22. // 方式一:
    23. /* export default ()=>{
    24. console.log('我是默认暴露的箭头函数');
    25. } */
    26. // 方式二:
    27. export default {
    28. msg: '默认暴露',
    29. foo() {
    30. console.log(this.msg);
    31. }
    32. }
    33. ## js/src/app.js
    34. //引入其他的模块
    35. //语法:import xxx from '路径'
    36. import module1 from './module1'
    37. import module2 from './module2'
    38. console.log(module1,module2); //undefined undefined

    译并在index.html中引入
    使用Babel将ES6编译为ES5代码(但包含CommonJS语法) :

    babel js/src -d js/lib


    使用Browserify编译js :

    browserify js/lib/app.js -o js/lib/bundle.js


    然后在index.html文件中引入

     <script type="text/javascript" src="js/lib/bundle.js"></script>

    参考:

    视频-尚硅谷

    博客

    最全面、最详细的“前端模块化”总结_编程三昧的博客-CSDN博客

    前端模块化详解(完整版)_浪里行舟的博客-CSDN博客

    前端模块化详解_最美的太阳-的博客-CSDN博客

  • 相关阅读:
    CSS中backdrop-filter与fliter属性
    redis之持久化(RDB、AOF)
    一个.Net版本的ChatGPT SDK
    SQL Server创建数据库
    FPGA快速创建项目
    Python利用PIL将png图像转jpg图像
    Matlab高光谱遥感数据处理与混合像元分解实践技术
    Apache Skywalking 安装部署、指标说明
    力扣labuladong一刷day5共3题
    MySQL8 创建函数报错:This function has none of DETERMINISTIC
  • 原文地址:https://blog.csdn.net/m0_74033724/article/details/133041341