如何使用jsdoc 3或jsdoc记录Require.js(AMD)模块?

28

我有两种类型的模块:

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;

});

当可能使用jsdoc时,我该如何使用jsdoc3来记录这个?

5个回答

16

这是我在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注释解释为由@lends标签引用的类的一部分。 在这种情况下,下一个对象文字是以function(Mediator) {开头的对象文字。 @name标签被删除,因此jsDoc会在源代码中查找函数名称等信息。
注意:我在与@lends标记相同的位置使用了@exports标记。虽然可以工作,但它会在文档中创建一个模块,而我只想为类生成文档。这种方式适合我!
一般的jsDoc参考资料

好的,很好……我会试一下然后告诉你! - 3logy
1
你同时使用了 @class@constructor 标签。它们是彼此的同义词。不要在构造函数上放置 @return - kzh
好的,谢谢你的建议。问题是:为什么不在构造函数中使用 @return? - marcusstenbeck
@lends 还有一个选项,可以添加 .prototype 后缀,这将把所有成员标记为实例而不是静态的。http://usejsdoc.org/tags-lends.html - Aram Kocharyan
回复晚了一年,但是在构造函数中不需要使用 @return,因为它会隐式地返回它所属的类。 - KhalilRavanna

9

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;

    });

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

8

接下来,我们看一下Muxa的回答中提到的链接,可以发现文档确实涉及RequireJS:

RequireJS库提供了一个define方法,允许您编写一个函数来返回一个模块对象。使用@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,另一个是类Turtleneck。类Turtleneck也将被记录为具有自己的属性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和其他标签/技术。相反,我建议尽量使用参考RequireJS文档中使用的@module@exports@alias标签。
我不确定如何记录你的RequireJS 'main'文件。如果我理解正确,你实际上并没有定义任何模块,而是执行了一个依赖于多个模块的一次性函数。

太好了,我终于让它工作了。谢谢!我试图将一个简单的配置哈希定义为模块,但当我只是在return { key: value, etc.};语句之前放置@module定义时,它似乎无法工作。我不得不声明一个var ModuleName = { key: value... };(在@module声明之前),然后在define函数的末尾返回var - Lambart

2

我的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模块内的构造函数中实现此行为,请将其声明为全局命名空间成员

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() {
}
});

1

看起来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 由此文件定义并导出。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接