JSDuck實戰

字數:2543javascript

閱讀時間:15分鐘html

前言

​ 上一篇文章咱們講述了JSDuck的詳細用法。那麼,本文筆者就以實例爲基礎,和你們一塊兒,從零開始,搭建一個簡單的API文檔——咱們的第一個API文檔V0.0.1。java

​ 上一篇文章的入口處 ===> JSDuck用法詳解json

正文

​ 首先,咱們肯定框架的基本內容:一個動物基類,而後派生出貓和狗兩個子類。動物基類中有一個動物描述屬性和吃飯方法,其派生類貓擁有奔跑、玩耍兩個方法,外加一個發出聲音的事件。微信

​ 總體內容就這麼多,很是簡單哈,那下面咱們就來看看該如何構建整個框架。markdown

1.構建基礎代碼

​ 磨刀不誤砍柴工,首先,咱們須要構建好基礎代碼。根據所需內容肯定,咱們須要構建一套完整的建立類和繼承類的方案。那麼,第一步,咱們建立一個base.js文件來盛放基礎代碼。app

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代碼基本一致,這裏就再也不多作累述了。

​ 至此,咱們全部的代碼構建工做就結束了,整個代碼結構以下圖所示

圖1

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": [
        "<script type='text/javascript'>",
        "Docs.otherProducts = [",
            "{text: 'Docs 3.0', href: 'http://***/3.0'},",
            "{text: 'Docs 2.0', href: 'http://***/2.0'},",
            "{text: 'Docs 1.0', href: 'http://***/1.0'}",
        "];",
        "</script>"
    ],
    "--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 ,就能夠看到咱們今天的勞動成果啦!

​ 曬一張成果圖,與你們共勉:

圖2

​ 關於JSDuck的學習和實踐的分享,到這裏就告一段落啦。但願對你們有所幫助,也隨時歡迎你們和筆者討論相關技術。

​ 全部源碼下載地址:https://pan.baidu.com/s/1dE88lPZ

歡迎關注個人微信公衆號:

相關文章
相關標籤/搜索