草庐IT

JS 模块化 - 03 AMD 规范与 Require JS

程序员优雅哥 (youyacoder) 2023-03-28 原文

1 AMD 规范介绍

AMD 规范,全称 Asynchronous Module Definition,异步模块定义,模块之间的依赖可以被异步加载。

AMD 规范由 Common JS 规范演进而来,前文介绍 Common JS 规范时说过,浏览器端无法直接使用 Common JS,需要使用 browserify 编译后才能运行。而 AMD 规范规范则专注于浏览器端。

1.1 定义模块

AMD 规范定义模块使用 define 函数,函数声明如下:

define(id?, dependencies?, factory)

参数含义:

- id:非必填,模块的名字。如果没有传该参数,模块的名字默认为模块加载器请求的指定脚本的名字
- dependencies:非必填,数组,定义的这个模块所需要依赖的模块的数组。如果定义的这个模块不依赖于其他模块,则不需要传递该参数。
- factory:必填,工厂方法。如果为对象,则表示这个模块输出的值;如果为函数,则是这个模块要干的事。

如果传递了 dependenciesdependencies 中依赖的每项模块会在当前模块的 factory 之前执行。

1.2 加载模块

与 Common JS 规范类似,加载模块使用 require 函数,但 AMD 规范中该函数有两个参数,语法格式如下:

require([module], callback)

参数含义:

- module:数组,要加载的模块数组。
- callback:模块加载成功之后要干的事。

2 Require JS

require.js 是符合 AMD 规范的 JS 库,使用 require.js 可以实现 AMD 规范,进行模块的定义和加载。

2.1 使用准备

首先下载 require.js 文件。require.js 可以从 github 下载。(不知道是不是网络原因,官网我打不开)

在项目中创建 lib 目录,将 require.js 文件复制到 lib 目录中。

2.2 初始化目录

lib 同级目录创建目录 modules,在 modules 目录中分别创建 module1.jsmodule2.js 代表两个模块。

同时下载 moment.js 文件,将其复制到 lib 目录中。

lib 同级目录创建入口 HTML 和 JS 文件,名字分别为:index.htmlindex.js.

此时目录结构为:

|- 03_AMD/
	|- lib/
		|- require.js
		|- moment.js
	|- modules/
		|- module1.js
		|- module2.js
	|- index.html
	|- index.js

index.html 文件中通过 script 标签引入 require.js 文件,同时指定 data-main 属性:

<script src="./lib/require.js" data-main="./index.js"></script>

data-main 属性指定了在加载完 require.js 属性后,执行的入口文件,该文件也称为 主模块 。咱们的主模块为 index.html 同级路径下的 index.js

2.3 路径配置

在入口 JS 文件 index.js 中对模块进行配置:

requirejs.config({
  baseUrl: './',
  paths: {
    m1: './modules/module1',
    m2: './modules/module2',
    moment: './lib/moment'
  },
  shim: {
    moment: {
      exports: 'moment'
    },
  }
})
  1. baseUrl 属性:指定了基本路径,后面模块路径配置都是相对于这个基本路径。
  2. paths 属性:配置各个模块的名称及对应文件路径(省略 .js 后缀)。上面分别给 module1.jsmodule2.jsmoment.js 三个模块命名为 m1m2moment。名字可以取其他名字,但路径要正确。
  3. shim 属性:当使用其他不符合 AMD 规范的模块时,可以使用该属性导出模块。(这里选择的 moment.js 是兼容 AMD 规范的库,无须配置到 shim 属性中,此处仅为了简单演示)

2.4 定义模块

前面创建了两个自定义模块,现在分别编写这两个模块。

module1.js 中定义一个简单的加法运算:

define(function () {
  console.log('in module1.')

  function sum(num1, num2) {
    console.log('module1 sum function.', num1, num2)
    return num1 + num2
  }

  return {
    sum
  }
})

module2.js 定义一个 calculate 函数,在该函数中需要调用 moment.js 中的格式化函数、 module1.js 中的 sum 函数,也就是说该模块(m2)依赖于 moment 模块 和 m1 模块:

define(['m1', 'moment'], function (m1, moment) {

  console.log('in module2.')

  function calculate (n1, n2) {
    console.log('begin calc: ', moment().format('YYYY MMM Do h:mm:ss a'))
    return m1.sum(n1, n2)
  }

  return {
    calculate
  }
})

2.5 使用模块

前面在主模块 index.js 中定义了模块的路径,现在继续在该文件中通过 require 函数使用其他模块:

// ...

require(['m2'], function (m2) {
  const result = m2.calculate(10, 20)
  console.log(result)
})

主模块中加载 m2 模块(module2.js),并调用 m2 模块中的 calculate 函数。

2.6 运行

在浏览器中运行 index.html,浏览器控制台输出如下:

主模块(index.js)依赖于 m2 模块(module2.js),m2 模块又依赖于 m1 模块(module1.js),故 require.js 会首先加载 module1.js,输出 in module1.,然后加载 module2.js, 输出 in module2.

m1m2moment 三个模块都加载完毕后,才会执行主模块中的 factory 工厂函数。

3 总结

AMD 规范的使用:

  • 定义模块:define 函数
  • 加载模块:require 函数

感谢你阅读本文,如果本文给了你一点点帮助或者启发,还请三连支持一下,点赞、关注、收藏,作者会持续与大家分享更多干货

有关JS 模块化 - 03 AMD 规范与 Require JS的更多相关文章

  1. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  4. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  5. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  6. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  7. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  8. ruby-on-rails - Controller 中的 Rails 辅助模块 - 2

    我有一个Controller,我想为这个Controller创建一个助手,我可以在不包含它的情况下使用它。我尝试像这样创建一个与Controller同名的助手classCars::EnginesController我创建的助手是moduleCars::EnginesHelperdefcheck_fuellogger.debug("chekingfuel")endend我得到的错误是undefinedlocalvariableormethod`check_fuel'for#有没有我遗漏的约定? 最佳答案 如果你真的想在Controll

  9. ruby-on-rails - 具有同名的模块和类 - 2

    我有一个模块stat存在于目录结构中:lib/stat_creator/stat/在lib/stat_creator/stat.rb中,我在lib/stat_creator/stat/目录中有我需要的文件,以及:moduleStatCreatormoduleStatendend当我使用该模块时,我将这些类称为StatCreator::Stat::Foo.new现在我想要一个存在于应用程序中的根Stat类。我在app/models中制作了我的Stat类,并在routes.rb中进行了设置。但是,如果我转到Rails控制台并尝试在应用程序/模型中使用Stat类,例如:Stat.by_use

  10. ruby-on-rails - 使用 rspec 和 rails 测试嵌套模块 - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Testingmodulesinrspec目前我正在使用rspec成功测试我的模块,如下所示:require'spec_helper'moduleServicesmoduleAppServicedescribeAppServicedodescribe"authenticate"doit"shouldauthenticatetheuser"dopending"authenticatetheuser"endendendendend我的模块位于应用程序/服务/services.rb应用程序/服务/app_servi

随机推荐