用过 Java 的都很熟悉 Javadoc, 只要在代码的方法上面写上相应的代码说明注解,那么使用一个 javadoc
命令就可以生成一个 API 说明文档。
JavaScript 本身并没有这样的功能,不过也有这样的工具:JSDOC。
基本用法
- 安装
# 全局安装即可
npm install -g jsdoc
- 使用
# 生成文件 `input.js` 的说明文档,并存放在 `docs` 目录
jsdoc input.js -d docs
# 使用配置文件config生成说明文档
jsdoc -c config.js
使用配置
一般来说,最好是使用配置文件去生成,这样,免得总是敲一长串命令。jsdoc支持 json和js文件作为配置示例:
JSON格式样例
{
"tags": {
"allowUnknownTags": true
},
"source": {
"include": [ ],
"exclude": [ ],
"includePattern": ".+\\.js(doc|x)?$",
"excludePattern": "(^|\\/|\\\\)_"
},
"plugins": [],
"recurseDepth": 10,
"templates": {
"cleverLinks": false,
"monospaceLinks": false,
"default": {
"outputSourceFiles": true
}
}
}
JavaScript格式样例
'use strict';
module.exports = {
"tags": {
"allowUnknownTags": true
},
"source": {
"include": [ /* array of paths to files to generate documentation for */ ],
"exclude": [ /* array of paths to exclude */ ],
"includePattern": ".+\\.js(doc|x)?$",
"excludePattern": "(^|\\/|\\\\)_"
},
"plugins": [],
"recurseDepth": 10,
"templates": {
"cleverLinks": false,
"monospaceLinks": false,
"default": {
"outputSourceFiles": true
}
}
}
个人更喜欢用js,因为json里面不能写注释。写好配置文件后,运行:
# 这里加个-r 参数,代表遍历文件夹下的子文件夹,配置文件里面 "recurseDepth": 10 代表最多递归10层目录
jsdoc -c config.js -r -d docs
常用配置项说明
项 | 类型 | 示例 | 说明 |
---|---|---|---|
plugins | Array[String] |
["plugins/markdown"] |
使用插件,附:支持插件 |
recurseDepth | int | 10 | 文件夹递归深度,只有在命令行加入了 -r 才有用,默认为10 |
source | Object | 参考上面的DEMO | 通过source可以灵活配置需要生成的文件 |
type | String | 支持”module”、”script” | module(默认):输入为文件,script:输入为脚本,通常不怎么使用 |
opts | Ojbect | {“template”:”templates/default”} | 命令行的配置形态,在这里配置一下可以不用在命令行输入了 |
opts.template | string | “templates/default” | 相当于 -t templates/default |
opts.encoding | string | “utf-8” | 相当于 -e utf8 |
opts.destination | string | “docs” | 相当于 as -d docs |
opts.recurse | boolean | true | 相当于 -r |
tags | Object | {“allowUnknownTags”: true} | Tag配置 |
templates | Object | 参考上面的DEMO | 模板配置 |
Tag说明
Tag 分为两类块Tag
和行Tag
,块Tag
即是以 @
开头的,行Tag
是使用大括号{}
包起来的, 比如 @param
就是块Tag
,{@link}
就是行Tag
。一般情况下我们使用的都是块Tag
行Tag
可以在块Tag
中使用,如果行Tag
里面的内容不是以@
开头,一般可以认为该Tag是一个数据类型比如 {string}
,{object}
,{CustomType}
等。比如以下代码即定义了一种类型,并可以链接去查看,比如以下代码:
/**
* @public
* @class
* @classdesc Person的定义
*/
class Person{
/**
* Person 构造器
* @constructs
* @param {string} name
* @param {number} age
*/
constructor(name,age) {
this.name = name;
this.age = age;
}
/**
* 获取姓名
* @return {string} 姓名
*/
getName(){
return this.name;
}
/**
* 返回本人的实体 {@link Person}
* @return {Person}
*/
getSelf(){
return this;
}
}
生成出来后结果如下,可以看到我返回的类型已经是链接的形式,可以点进去查看
JSDOC支持60多个Tag,有兴趣的可以去官方网站 看看,我这里把我自己用到常用不常用的Tag整理一下,并按个人的理解排了下,这些Tag一般根据名字都可以看出具体功能,所以不做说明,如果玩过Java的注解之类的基本可以一看就懂。
功能 | Tag |
---|---|
修饰 | @public @private @property @readonly @static @default @global @abstract |
结构1 | @param @return @class @constructs @enum @instance @package @function @constant |
结构2 | @typedef @memberof @module @export @namespace |
结构3 | @requires @override @implements @external |
文档 | @version @author @since @see @deprecated @copyright @description @ignore @license @summary |
自定义皮肤
说明:官方提供的templates
配置只能简单的配置底部是否显示时间,或是导航栏里面显示长名称的配置,虽然提供了templates.default.layoutFile
配置项可以让我们自己写个模板文件去替换掉官方的layout.tmpl
,但实际上我们一般不会自己去开发一套皮肤。
通常jsdoc
可以和gulp
,grunt
等一起去用,在gulp
的插件里面有丰富的jsdoc模板,配置也很简单,除了默认的模板外,官方提供了不少皮肤,可以去参考.
CommonJS模块化
目前官方有ES2015
, CommonJS
, AMD
三种模块化方案的DEMO,都是 使用 @module 对脚本进行模块化,细节略有不同,由于本人使用的是CommonJS
,这方面碰到几个坑(也不能算坑,就是不知道如何让文档和代码一样结构和条理保持清晰。这里个人提供一些方案,不分排名,各有用途,仅供参考。
使用全局的命名空间 @namespace
使用一个入口文件定义一些全局的命名空间 @namespace
,模块化的目录里面也可以在入口文件里面定义,其它文件都通过@memberof
指定成为命名空间的成员
DEMO:在输入范围内建一个xxx.jsdoc
文件,编辑
这里在这个文件里面定义了两个@namespace
/**
@namespace util
@description ### Utils公用工具,页面上的公用方法,验证等。
1. {@link util.ValidateUtil ValidateUtil} : 验证Util
2. {@link util.CommonUtil CommonUtil} : 公用Util
*/
/**
@namespace comments
@description ### 开发中常用的组件
1. xxx
2. xxx
*/
- 在对应的文件里面将对应的对象标记为namespace的成员
// ValidateUtil.js
/**
* @name ValidateUtil
* @memberof util
* @description 验证UTIL
*/
// CommonUtil.js
/**
* @name CommonUtil
* @memberof util
* @description 公用UTIL
*/
// xxxxxxx.js
/**
* @name xxxxxxx
* @memberof comments
* @description xxxxxxx组件
*/
使用一个@module
,@export
模块化
这两个关键字看上去不一样,但实际上是一样的效果,都是模块化,为什么有两个,主要是我们的代码常常有以下两种:
代码一:都写好了,导出时指定KV,这一种我们使用@module
,定义了module后再定义成员。
/**
* @module Ajax
* @description ### 说明:XXX
*/
/**
* @function
* /
var a = function(){
}
/**
* @member
* /
var b = 1;
module.exports = {
a:a,
b:b
};
说明,以上代码并非一定要使用@module
,使用@export
也可以同样完成,只不过需要把注释写在module.export={...}
里面,感觉很不爽。
代码二:直接导出对象,这只使用@export
/**
* @exports X
*/
class X{
/**
* @function
* /
a(){
}
/**
* @function
* /
b(){
}
}
module.exports = new X();
虽然不怎么合理,但通常个人喜欢把一大块的module定义成一个namespace,而静态工具定义成module,生成出来的页面虽然有些对不上,但感觉排的很清晰,当然这和项目代码也有一定关系。
其它
如果使用工具前,代码里面存在 /****/
这样的注释,会当作文档进行处理,可以选择优化,或使用 //
注释替代。
一般情况下,jsodc都会自动识别代码里面的类型,但是导出一个方法时,我们可以手动定义类型,以及方法的名称,比如
/**
* @function methodName
* @memberof namespace
* @description 这是namespace的method
*/
module.exports = function(){
}
JSDOC是一个很容易入门的工具,使用起来也很简单,但如果项目代码较多,结构复杂,生成出漂亮的文档就比较麻烦了,合理使用@namespace
,@module
, @typedef
, @memberof
等结构体。
另外也可以通过控制项目的结构,只选择一些核心的文档去生成。
最后,sublime里面的jsodc插件可以在写代码的时候自动插入jsdoc模板,但个人是不推荐去装的,一般情况下没太大必要。