资讯专栏INFORMATION COLUMN

JSDuck实战

kel / 2334人阅读

摘要:我们先声明了类,在类的注释上添加标签表示静态类。静态类中包含一个方法,实现了一个简单的扩展功能,后面类的继承需要用到这个接口。这里需要注意,静态类中,所有的成员也都是静态的。

字数:2543

阅读时间:15分钟

前言

​ 上一篇文章我们讲述了JSDuck的详细用法。那么,本文笔者就以实例为基础,和大家一起,从零开始,搭建一个简单的API文档——我们的第一个API文档V0.0.1。

​ 上一篇文章的入口处 ===> JSDuck用法详解

正文

​ 首先,我们确定框架的基本内容:一个动物基类,然后派生出猫和狗两个子类。动物基类中有一个动物描述属性和吃饭方法,其派生类猫拥有奔跑、玩耍两个方法,外加一个发出声音的事件。

​ 整体内容就这么多,非常简单哈,那下面我们就来看看该如何构建整个框架。

1.构建基础代码

​ 磨刀不误砍柴工,首先,我们需要构建好基础代码。根据所需内容确定,我们需要构建一套完整的创建类和继承类的方案。那么,第一步,我们创建一个base.js文件来盛放基础代码。

    var GM = {};
    window.GM = GM;

    /**
     * 基础类的通用API类
     * @class GM.Util
     * @author lsjcoder
     * @docauthor lsjcoder
     * @static
     */
    GM.Util = {
        /**
         * 扩展对象
         * @method extend
         * @static
         * @param dest
         *            {Object} 任意对象
         * @return {Object} 扩展后的对象
         */
        extend : function(dest) { // (Object[, Object, ...]) ->
            var sources = Array.prototype.slice.call(arguments, 1), i, j, len, src;

            for (j = 0, len = sources.length; j < len; j++) {
                src = sources[j] || {};
                for (i in src) {
                    if (src.hasOwnProperty(i)) {
                        dest[i] = src[i];
                    }
                }
            }
            return dest;
        }
    };

​ 在创建好的文件内,我们先编写上述代码。我们先声明了类 GM.Util ,在类的注释上添加 @static标签表示静态类。静态类中包含一个方法 extend ,实现了一个简单的扩展功能,后面类的继承需要用到这个接口。(这里需要注意,静态类中,所有的成员也都是静态的。因此,所有的成员必须加上@static标签)。

    /**
     * 所有类的基类
     * @class GM.Class
     */
    GM.Class = function() {
        /**
         * @property {String} version 版本号
         * @readonly
         */
        this.version = "0.0.1";
    };

​ 声明顶层基类 GM.Class ,框架中所有的类都派生自该类。类中声明了一个 version 属性,该属性是字符串类型,并且是只读属性。

    /**
     * 基类的扩展方法
     * @method extend
     * @static
     * @param {Object}
     *            props 包含需要扩展的成员的对象
     * @return {Object} 扩展后的类
     */
    GM.Class.extend = function(props) {
        // extended class with the new prototype
        var NewClass = function() {

            // call the constructor
            if (this.initialize) {
                this.initialize.apply(this, arguments);
            }

            // call all constructor hooks
            if (this._initHooks) {
                this.callInitHooks();
            }
        };

        // instantiate class without calling constructor
        var F = function() {
        };
        F.prototype = this.prototype;

        var proto = new F();
        proto.constructor = NewClass;

        NewClass.prototype = proto;

        // inherit parent"s statics
        for ( var i in this) {
            if (this.hasOwnProperty(i) && i !== "prototype") {
                NewClass[i] = this[i];
            }
        }

        // mix static properties into the class
        if (props.statics) {
            GM.Util.extend(NewClass, props.statics);
            delete props.statics;
        }

        // mix includes into the prototype
        if (props.includes) {
            GM.Util.extend.apply(null, [ proto ].concat(props.includes));
            delete props.includes;
        }

        // merge options
        if (props.options && proto.options) {
            props.options = GM.Util.extend({}, proto.options, props.options);
        }

        // mix given properties into the prototype
        GM.Util.extend(proto, props);

        proto._initHooks = [];

        var parent = this;
        // jshint camelcase: false
        NewClass.__super__ = parent.prototype;

        // add method for calling all hooks
        proto.callInitHooks = function() {

            if (this._initHooksCalled) {
                return;
            }

            if (parent.prototype.callInitHooks) {
                parent.prototype.callInitHooks.call(this);
            }

            this._initHooksCalled = true;

            for (var i = 0, len = proto._initHooks.length; i < len; i++) {
                proto._initHooks[i].call(this);
            }
        };

        return NewClass;
    };

​ 基类GM.Class中包含一个静态方法,用于实现类的继承机制。后续代码中类的封装和继承都是使用该方法完成的。

    /**
     * @enum GM.Enum.Sex 性别枚举
     */
    GM.Enum.Sex = {
        /**
         * 男
         */
        "0":"男",
        /**
         * 女
         */
        "1":"女"
    }

​ 基础代码中,还声明了一个性别枚举,以供后续使用。

​ 至此,基础代码构建完毕。

2.构建动物基类代码

​ 在这个环节中,我们需要构建一个动物基类。首先,我们创建一个animal.js文件盛放代码。

​ 文件完整代码如下:

    /**
     * 动物类
     * @class GM.Animal
     * @alias Animal
     * @abstract
     * @extends GM.Class
     * @new
     * @author lsjcoder
     * @docauthor lsjcoder
     */
    GM.Animal = GM.Class.extend({
        /**
         * @method constructor
         * @cfg {Object} configs 传入参数
         * @cfg {String} configs.name 姓名
         * @cfg {Number} configs.age 年龄
         * @cfg {"男"/"女"} configs.sex 性别
         */
        initialize:function(configs){
            this.props.name = configs.name;
            this.props.age = configs.age;
            this.props.sex = configs.sex;
        },
        /**
         * @property {Object} props 属性
         * @property {String} props.name 姓名
         * @property {Number} props.age 年龄
         * @property {GM.Enum.Sex} props.sex 性别
         * @property {String} props.color 颜色
         * @property {String} props.type 品种
         */
        props:{
            name:"",
            age:0,
            sex:"男",
            color:"",
            type:""
        },
        /**
         * 吃饭
         * @method eat
         * @abstract
         * @param  {String} food 食物
         * @return {Boolean} 是否进食
         */
        eat:function(food){
            if(food != null || food !== ""){
                return true;
            }
            return false;
        }
    });

​ 我们创建了一个动物类 GM.Animal ,该类不需要实现任何方法,所以,我们给他添加一个抽象标签 @abstract表明该类是一个抽象类。@extends GM.Class表明了该类派生自 GM.Class 类,@new标签表示此类是这个版本新增加的内容。

​ 类中有一个 initialize 方法,它是类的构造函数。所以我们用注释 @method constructor标记它为构造函数,然后使用 @cfg标签描述构造函数所需参数。这里,构造函数所需参数是一个对象,对象中有多个属性,所以我们使用如上配置方式来分别描述每一个属性。类中还有一个 props 属性,描述了动物的基本信息,该属性也是一个对象,注释方式同上述 @cfg 。最后,类中还有抽象方法 eat ,该方法接收一个字符串类型参数并返回一个布尔类型的结果。

3.构建子类猫和狗的代码

​ 接下来,我们需要构建动物类的两个派生类:猫类和狗类。我们分别创建两个代码文件:cat.js、dog.js。

​ cat.js文件中代码如下:

    /**
     *猫
     * 
     *```
     *示例:
     *var pCat = new GM.Cat({
     *        name:"Kity",
     *        age:1,
     *        sex:"女"
     *})
     *```
     *
     * @class GM.Cat
     * @extends GM.Animal
     * @alias Cat
     * @author lsjcoder
     * @docauthor lsjcoder
     * @uses GM.Dog
     *     
     */
    GM.Cat = GM.Animal.extend({
        /**
         * @method constructor
         * @cfg {Object} configs 传入参数
         * @cfg {String} configs.name 姓名
         * @cfg {Number} configs.age 年龄
         * @cfg {"男"/"女"} configs.sex 性别
         */
        initialize:function(configs){
            this.props.name = configs.name;
            this.props.age = configs.age;
            this.props.sex = configs.sex;

            /**
             * @event say 发出叫声
             * @param {GM.Cat} this 当前实例
             * @param {String} value 叫声
             */
            this.fireEvent("say", this, value);
        },
        /**
         * @method run 奔跑,已经废弃,请使用 {@link GM.Cat#startRun} 方法代替
         * @removed
         */
        run:function(){
            this.bRun = true;
        },
        /**
         * @method startRun 开始奔跑
         * @return {Boolean} 开始奔跑是否成功
         */
        startRun:function(){
            if(this.bRun === true){
                return false;
            }
            this.bRun = true;
            return true;
        },
        /**
         * @method playWithDog 与小狗一起玩耍
         * @param  {GM.Dog} pDog 小狗
         */
        playWithDog:function(pDog){
            this.player = pDog;
        }
    });

​ 类 GM.Cat 派生自GM.Animal ,其中需要强调的有以下几点:

     *```
     *示例:
     *var pCat = new GM.Cat({
     *        name:"Kity",
     *        age:1,
     *        sex:"女"
     *})
     *```

​ 这段注释是描述了一个使用该类的示例,使用的是markdown语法来注释的。在文字的首尾分别添加符号 "`" 就可以表明注释代码,但是注意该符号一定要换行使用,否则无法生效。

    /**
    * @event say 发出叫声
    * @param {GM.Cat} this 当前实例
    * @param {String} value 叫声
    */
    this.fireEvent("say", this, value);

​ 这段注释表明,类 GM.Cat 拥有一个名称为 “say” 的事件,该事件有两个参数,一个是当前实例,另外一个是字符串类型的叫声。

* @property {"男"/"女"} configs.sex 性别
* @property {GM.Enum.Sex} props.sex 性别

​ 上面代码是描述枚举的两种方式。

​ dog.js代码和cat.js代码基本一致,这里就不再多做累述了。

​ 至此,我们所有的代码构建工作就结束了,整个代码结构如下图所示

4.生成文档

​ 接下来,就是最后一步了——使用工具生成文档。

​ 我们在与代码同级的目录下,创建一个 jsduck.json 配置文件,以便工具使用。配置文件内容如下:

{
    "--title": "我是一个示例文档",
    "--welcome": "welcome.html",
    "--warnings": ["-link", "-no_doc"],
    "--seo": true,
    "--": [
        "./code"
    ],
    "--output": "./docs",
    "--examples-base-url": "../examples",
    "--examples": "./examples.json",
    "--body-html": [
        ""
    ],
    "--categories":"./categories.json"
}

​ 我们配置输入文件为整个代码文件夹,解析所有代码并生成文档。这里,我们配置了一个 examples.json 文件作为示例配置文件,文件内容如下:

[
    {
        "title": "样例展示",
        "items": [
            {
                "name": "test-example",
                "title": "cat类使用示例",
                "description": "cat类使用示例",
                "url": "/example.html",
                "icon": "user.png",
                "status": "updated"
            }
        ]
    }
]

​ 这里,我们配置了 examples 目录下的 example.html 文件作为示例页面。

​ 然后,里面还配置了一个 categories.json 文件作为代码分类配置,文件内容如下:

 [
    {
        "name": "Common",
        "groups": [
            {
                "name": "Base",
                "classes": [
                    "GM.Class",
                    "GM.Util"
                ]
            },
            {
                "name": "Animal",
                "classes": [
                    "GM.Animal",
                    "GM.Cat",
                    "GM.Dog"
                ]
            }
        ]
    }
]

​ 该配置将代码中的类分为了两组:Base 和 Animal 。这里需要注意,JSDuck中代码分类配置限制死了,只能配三级结构,不能做其他级别的配置。

​ 好啦!至此,所有的准备工作就全部完成啦!

​ 此时,我们只需要在 jsduck.json 目录下,轻轻地输入命令 jsduck ,就可以看到随着命令执行的结束,同级目录下生成了一个 docs文件夹。这个文件夹就是我们的文档成果,进入该文件夹,打开页面 template.html ,就可以看到我们今天的劳动成果啦!

​ 晒一张成果图,与大家共勉:

​ 关于JSDuck的学习和实践的分享,到这里就告一段落啦。希望对大家有所帮助,也随时欢迎大家和笔者讨论相关技术。

​ 所有源码下载地址:https://pan.baidu.com/s/1dE88lPZ

欢迎关注我的微信公众号:

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/90722.html

相关文章

  • JSDuck用法详解

    摘要:语法父类名表示当前类继承于哪个类的标签。成员标签成员标签作用于类中的配置属性函数事件。表明可被子类继承,和一起使用。示例获取圆的面积圆的半径面积值作用于函数,表明函数的标签。作用于函数,表明构造函数参数的标签,用法同。 字数:3692字 阅读时间:15分钟 前言 ​ 首先,咱们有一个前提,JSDuck对我们而言只是一个便于API查看的文档化工具。因此,只要它能够满足我们文...

    xiaochao 评论0 收藏0
  • JSDuck 与 AngularJS 融合技巧

    摘要:融合思路解决这个问题,有两种思路。给我们带来了以下新成员模块服务指令筛选器和控制器。与其他类是通过类的名称区分的,名称统一以结尾。这种处理方式是一种折中方案,如果想要更加规范优雅的话,建议使用自定义标签来解决。 字数:1568 阅读时间:10分钟 前言   前面,我们以一个实战案例来详细说明了如何在实际开发中使用JSDuck工具。但是,并不是所有的时候,代码的封装方式都受我们控制的。...

    CarterLi 评论0 收藏0
  • 五分钟玩转文档化工具JSDuck

    摘要:我们在对现在较主流的五个文档工具分别作了调研和尝试,得到结论如下工具优点缺点提供了完整的模板开发事件触发等接口,使用非常灵活。至此,的环境部署已经全部完成了。 字数:981 阅读时间:5分钟 选型依据 ​ 在经历了数个上线的项目之后,笔者所在的团队已经沉淀了一个相对稳定版本的前端框架。因此,我们需要出具一套框架API文档,以便公司其他成员的使用和框架的后期维护。我们在对...

    rickchen 评论0 收藏0
  • Javascript自动化文档工具:YUI Doc, JSDoc 3, JSDuck等比较

    摘要:本文比较了种较为主流的注释文档生成工具。应该说是非常适合开源项目多个作者共同维护的一个文档工具。最后我选择了作为文档生成的工具。为了支持多种语言,它仅对注释块内部的内容进行解析。 最近随着写Node以及独立的CommonJS模块越来越多,我发现有一份好的文档不仅可以帮助自己在应用这些接口的时候不至于迷糊,而且对于共同开发的情况下,能够省去大量团队的交流和Debug的时间。 本文比较了...

    tyheist 评论0 收藏0
  • Jsduck的使用

    摘要:简介是众多开源项目中的一个,它是使用编写的文档生成器。系统环境变量,对所有用户起作用。使用可通过配置,也可通过直接在命令行写参数来使用。配置进入项目目录,配置文件,类似以下的写法运行命令,即可在文件夹下找到自动生成的文档。 简介 jsduck是senchalabs众多开源项目中的一个,它是使用ruby编写的 javascript API文档生成器。不像JSDoc一样,不按照符合JSDo...

    alaege 评论0 收藏0

发表评论

0条评论

kel

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<