【问题标题】:How to document a Require.js (AMD) Modul with jsdoc 3 or jsdoc?如何使用 jsdoc 3 或 jsdoc 记录 Requirejs (AMD) 模块?
【发布时间】:2012-04-27 16:19:11
【问题描述】:

我有两种类型的模块:

Require.js 主文件

    require.config({
      baseUrl: "/another/path",
      paths: {
        "some": "some/v1.0"
      },
      waitSeconds: 15,
      locale: "fr-fr"
    });


    require( ["some/module", "my/module", "a.js", "b.js"],
      function(someModule,    myModule) {
      }
    );

中介者模式:

define([], function(Mediator){

var channels = {};
if (!Mediator) Mediator = {};  

Mediator.subscribe = function (channel, subscription) {   
  if (!channels[channel]) channels[channel] = [];
   channels[channel].push(subscription);
};

Mediator.publish = function (channel) {
  if (!channels[channel]) return;
  var args = [].slice.call(arguments, 1);
  for (var i = 0, l = channels[channel].length; i < l; i++) {
    channels[channel][i].apply(this, args);
  }
};

return Mediator;

});

如果可能的话,我如何使用 jsdoc3 来记录这一点?

【问题讨论】:

    标签: javascript requirejs jsdoc js-amd


    【解决方案1】:

    这是我关于 SO 的第一个答案,请告诉我如何改进未来的答案。

    你的具体例子

    这两天我一直在寻找答案,但似乎没有一种方法可以自动记录 RequireJS AMD 模块而没有一些冗余(例如重复的函数名称)。 Karthrik 的回答在生成文档方面做得很好,但是如果代码中的某些内容被重命名,文档仍然会从 jsDoc 标记中的内容生成。

    我最终做的是以下内容,这是根据 Karthik 的示例进行调整的。注意第 1 行的 @lends 标记,以及从 jsDoc 注释块中删除的 @name 标记。

     define([], /** @lends Mediator */ function(Mediator){
        /** 
         * Mediator class
         * This is the interface class for user related modules
         * @class Mediator
         */
    
        var channels = {};
        if (!Mediator) Mediator = {};  
    
        /**
          * .... description goes here ...
          * @function 
          *
          * @param {Number} channel  ..... 
          * @param {String} subscription ..............
          * @example
          * add the sample code here if relevent.
          * 
          */        
        Mediator.subscribe = function (channel, subscription) {   
          if (!channels[channel]) channels[channel] = [];
           channels[channel].push(subscription);
        };
    
        Mediator.publish = function (channel) {
          if (!channels[channel]) return;
          var args = [].slice.call(arguments, 1);
          for (var i = 0, l = channels[channel].length; i < l; i++) {
            channels[channel][i].apply(this, args);
          }
        };
    
    return Mediator;
    
    });
    

    据我了解,@lends 标记会将下一个对象文字中的所有 jsDoc cmets 解释为 @lends 标记引用的类的一部分。在这种情况下,下一个对象字面量是以function(Mediator) { 开头的字面量。 @name 标签被移除,以便 jsDoc 在源代码中查找函数名称等。

    注意:我在放置@lends 标签的地方使用了@exports 标签。虽然这可行,但它会在文档中创建一个模块……我只想为该类生成文档。这种方式对我有用!

    一般 jsDoc 参考

    【讨论】:

    • 很好...我会试一试告诉你!
    • 您同时使用了@class@constructor 标签。它们是彼此的同义词。也不要将@return 放在构造函数上。
    • 好的,感谢您的提示。问题:为什么不在构造函数中使用@return?
    • @lends 还可以选择添加.prototype 后缀,它将所有成员标记为实例而非静态。 usejsdoc.org/tags-lends.html
    • 回复晚了一年,但你不要在构造函数上使用@return,因为它隐式返回它是构造函数的类。
    【解决方案2】:

    jsDoc 似乎不喜欢“define”和“require”调用。

    所以,我们最终使用多个标签来制作 jsDoc 工具来获取构造函数和其他特定的类方法。请看下面的例子: 我刚刚从我的源代码中复制粘贴,并将其替换为您的类名和方法名。希望它对你有用。

        define([], function(Mediator){
            /** 
             * Mediator class
             * This is the interface class for user related modules
             * @name Mediator
             * @class Mediator
             * @constructor
             * @return Session Object
             */
    
            var channels = {};
            if (!Mediator) Mediator = {};  
    
            /**
              * .... description goes here ...
              * @name Mediator#subscribe
              * @function 
              *
              * @param {Number} channel  ..... 
              * @param {String} subscription ..............
              * @example
              * add the sample code here if relevent.
              * 
              */        
            Mediator.subscribe = function (channel, subscription) {   
              if (!channels[channel]) channels[channel] = [];
               channels[channel].push(subscription);
            };
    
            Mediator.publish = function (channel) {
              if (!channels[channel]) return;
              var args = [].slice.call(arguments, 1);
              for (var i = 0, l = channels[channel].length; i < l; i++) {
                channels[channel][i].apply(this, args);
              }
            };
    
        return Mediator;
    
        });
    

    注意:上述记录 JS 代码的方法在我们使用 jsDoc 时效果很好。还没有机会尝试 jsDoc3。

    【讨论】:

      【解决方案3】:

      通过link from Muxa's answer,我们看到文档确实特别提到了RequireJS:

      RequireJS 库提供了一个定义方法,允许您编写一个函数来返回一个模块对象。使用 @exports 标记来说明对象文字的所有成员都应记录为模块的成员。

      模块示例

      define('my/shirt', function () {
         /** 
          * A module representing a shirt.
          * @exports my/shirt
          * @version 1.0
          */
          var shirt = {
      
              /** A property of the module. */
              color: "black",
      
              /** @constructor */
              Turtleneck: function(size) {
                  /** A property of the class. */
                  this.size = size;
              }
          };
      
          return shirt;
      });
      

      所以在上面的例子中,我们看到 jsdoc 将解析一个my/shirt 模块 并将其记录为有两个成员:一个属性color,还有一个类TurtleneckTurtleneck 类也将被记录为拥有自己的属性 size

      构造函数模块示例

      使用 @alias 标记简化在 RequireJS 中记录构造函数模块。

      /** 
       * A module representing a jacket.
       * @module jacket
       */
      define('jacket', function () {
          /**
           * @constructor
           * @alias module:jacket
           */
          var exports = function() {
          }
      
          /** Open and close your Jacket. */
          exports.prototype.zip = function() {
          }
      
          return exports;
      });
      

      如果您将构造函数导出为模块,该模块将用作实例化对象的类,则上述内容是您想要使用的。总而言之,我不确定使用@lends 和其他已推荐的标签/技术。相反,我会尝试坚持使用documentation referencing RequireJS 中使用的@module@exports@alias 标签。

      我不确定你应该如何记录你的 requirejs 'main' 文件。如果我理解正确,您实际上并没有在那里定义任何模块,而是执行依赖于多个模块的一次性功能。

      【讨论】:

      • 很好,我终于让它工作了。谢谢!我试图将一个简单的配置哈希定义为一个模块,但是当我将 @module 定义放在 return { key: value, etc.}; 语句之前时,它似乎不起作用。我必须声明一个var ModuleName = { key: value... };(前面是@module 声明),然后在defined 函数的末尾返回var
      【解决方案4】:

      我的 AMD 课程使用稍微不同的形式,但 JSDoc 也没有记录它们,所以我想我会分享对我有用的方法。

      自动添加全局命名空间中的构造函数:

      /**
      * @classdesc This class will be documented automatically because it is not in
      * another function.
      * @constructor
      */
      function TestClassGlobal() {
      /**
      * This is a public method and will be documented automatically.
      */
      this.publicMethod = function() {
      };
      }
      

      如果您希望 AMD 模块内的构造函数具有此行为,请将其声明为 global命名空间的成员

      define([], function() {
      /**
      * @classdesc This won't be automatically documented unless you add memberof,
      * because it's inside another function.
      * @constructor
      * @memberof Namespace
      */
      function TestClassNamespace() {
      }
      
      /**
      * @classdesc This won't be automatically documented unless you add global,
      * because it's inside another function.
      * @constructor
      * @global
      */
      function TestClassForcedGlobal() {
      }
      });
      

      【讨论】:

        【解决方案5】:

        看起来事情在 JSDoc3 中变得简单多了。以下对我有用:

        中介者作为一个模块

        /**
         * Mediator Module
         * @module Package/Mediator
         */
        define([], function(Mediator){
        
          var channels = {};
          if (!Mediator) Mediator = {};  
        
          /**
           * Subscribe
           * @param  {String} channel Channel to listen to
           * @param  {Function} subscription Callback when channel updates
           * @memberOf module:Package/Mediator
           */
          Mediator.subscribe = function (channel, subscription) {   
            if (!channels[channel]) channels[channel] = [];
             channels[channel].push(subscription);
          };
        
          /**
           * Publish
           * @param  {String} channel  Channel that has new content
           * @memberOf module:Package/Mediator
           */
          Mediator.publish = function (channel) {
            if (!channels[channel]) return;
            var args = [].slice.call(arguments, 1);
            for (var i = 0, l = channels[channel].length; i < l; i++) {
              channels[channel][i].apply(this, args);
            }
          };
        
          return Mediator;
        
        });
        

        但是,我可能会对代码进行以下更改:

        /**
         * Mediator Module
         * @module Package/Mediator
         */
        define([], function(){
        
          var channels = {};
          var Mediator = {}
        
          ...
        

        原因是,模块说它定义了Mediator,但似乎借用了Mediator 的其他实例。我不确定我是否理解。在这个版本中,很明显Mediator 是由这个文件定义并导出的。

        【讨论】:

          猜你喜欢
          • 2015-11-27
          • 2017-01-17
          • 2014-02-11
          • 2020-02-09
          • 2017-11-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-19
          相关资源
          最近更新 更多