摘要:我們先聲明了類,在類的注釋上添加標簽表示靜態(tài)類。靜態(tài)類中包含一個方法,實現(xiàn)了一個簡單的擴展功能,后面類的繼承需要用到這個接口。這里需要注意,靜態(tài)類中,所有的成員也都是靜態(tài)的。
字數(shù):2543
閱讀時間:15分鐘
前言? 上一篇文章我們講述了JSDuck的詳細用法。那么,本文筆者就以實例為基礎,和大家一起,從零開始,搭建一個簡單的API文檔——我們的第一個API文檔V0.0.1。
? 上一篇文章的入口處 ===> JSDuck用法詳解
正文? 首先,我們確定框架的基本內(nèi)容:一個動物基類,然后派生出貓和狗兩個子類。動物基類中有一個動物描述屬性和吃飯方法,其派生類貓擁有奔跑、玩耍兩個方法,外加一個發(fā)出聲音的事件。
? 整體內(nèi)容就這么多,非常簡單哈,那下面我們就來看看該如何構(gòu)建整個框架。
1.構(gòu)建基礎代碼? 磨刀不誤砍柴工,首先,我們需要構(gòu)建好基礎代碼。根據(jù)所需內(nèi)容確定,我們需要構(gòu)建一套完整的創(chuàng)建類和繼承類的方案。那么,第一步,我們創(chuàng)建一個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; } };
? 在創(chuàng)建好的文件內(nèi),我們先編寫上述代碼。我們先聲明了類 GM.Util ,在類的注釋上添加 @static標簽表示靜態(tài)類。靜態(tài)類中包含一個方法 extend ,實現(xiàn)了一個簡單的擴展功能,后面類的繼承需要用到這個接口。(這里需要注意,靜態(tài)類中,所有的成員也都是靜態(tài)的。因此,所有的成員必須加上@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中包含一個靜態(tài)方法,用于實現(xiàn)類的繼承機制。后續(xù)代碼中類的封裝和繼承都是使用該方法完成的。
/** * @enum GM.Enum.Sex 性別枚舉 */ GM.Enum.Sex = { /** * 男 */ "0":"男", /** * 女 */ "1":"女" }
? 基礎代碼中,還聲明了一個性別枚舉,以供后續(xù)使用。
? 至此,基礎代碼構(gòu)建完畢。
2.構(gòu)建動物基類代碼? 在這個環(huán)節(jié)中,我們需要構(gòu)建一個動物基類。首先,我們創(chuàng)建一個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 傳入?yún)?shù) * @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; } });
? 我們創(chuàng)建了一個動物類 GM.Animal ,該類不需要實現(xiàn)任何方法,所以,我們給他添加一個抽象標簽 @abstract表明該類是一個抽象類。@extends GM.Class表明了該類派生自 GM.Class 類,@new標簽表示此類是這個版本新增加的內(nèi)容。
? 類中有一個 initialize 方法,它是類的構(gòu)造函數(shù)。所以我們用注釋 @method constructor標記它為構(gòu)造函數(shù),然后使用 @cfg標簽描述構(gòu)造函數(shù)所需參數(shù)。這里,構(gòu)造函數(shù)所需參數(shù)是一個對象,對象中有多個屬性,所以我們使用如上配置方式來分別描述每一個屬性。類中還有一個 props 屬性,描述了動物的基本信息,該屬性也是一個對象,注釋方式同上述 @cfg 。最后,類中還有抽象方法 eat ,該方法接收一個字符串類型參數(shù)并返回一個布爾類型的結(jié)果。
3.構(gòu)建子類貓和狗的代碼? 接下來,我們需要構(gòu)建動物類的兩個派生類:貓類和狗類。我們分別創(chuàng)建兩個代碼文件: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 傳入?yún)?shù) * @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 發(fā)出叫聲 * @param {GM.Cat} this 當前實例 * @param {String} value 叫聲 */ this.fireEvent("say", this, value); }, /** * @method run 奔跑,已經(jīng)廢棄,請使用 {@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 ,其中需要強調(diào)的有以下幾點:
*``` *示例: *var pCat = new GM.Cat({ * name:"Kity", * age:1, * sex:"女" *}) *```
? 這段注釋是描述了一個使用該類的示例,使用的是markdown語法來注釋的。在文字的首尾分別添加符號 "`" 就可以表明注釋代碼,但是注意該符號一定要換行使用,否則無法生效。
/** * @event say 發(fā)出叫聲 * @param {GM.Cat} this 當前實例 * @param {String} value 叫聲 */ this.fireEvent("say", this, value);
? 這段注釋表明,類 GM.Cat 擁有一個名稱為 “say” 的事件,該事件有兩個參數(shù),一個是當前實例,另外一個是字符串類型的叫聲。
* @property {"男"/"女"} configs.sex 性別 * @property {GM.Enum.Sex} props.sex 性別
? 上面代碼是描述枚舉的兩種方式。
? dog.js代碼和cat.js代碼基本一致,這里就不再多做累述了。
?
? 至此,我們所有的代碼構(gòu)建工作就結(jié)束了,整個代碼結(jié)構(gòu)如下圖所示
4.生成文檔? 接下來,就是最后一步了——使用工具生成文檔。
? 我們在與代碼同級的目錄下,創(chuàng)建一個 jsduck.json 配置文件,以便工具使用。配置文件內(nèi)容如下:
{ "--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 文件作為示例配置文件,文件內(nèi)容如下:
[ { "title": "樣例展示", "items": [ { "name": "test-example", "title": "cat類使用示例", "description": "cat類使用示例", "url": "/example.html", "icon": "user.png", "status": "updated" } ] } ]
? 這里,我們配置了 examples 目錄下的 example.html 文件作為示例頁面。
? 然后,里面還配置了一個 categories.json 文件作為代碼分類配置,文件內(nèi)容如下:
[ { "name": "Common", "groups": [ { "name": "Base", "classes": [ "GM.Class", "GM.Util" ] }, { "name": "Animal", "classes": [ "GM.Animal", "GM.Cat", "GM.Dog" ] } ] } ]
? 該配置將代碼中的類分為了兩組:Base 和 Animal 。這里需要注意,JSDuck中代碼分類配置限制死了,只能配三級結(jié)構(gòu),不能做其他級別的配置。
? 好啦!至此,所有的準備工作就全部完成啦!
? 此時,我們只需要在 jsduck.json 目錄下,輕輕地輸入命令 jsduck ,就可以看到隨著命令執(zhí)行的結(jié)束,同級目錄下生成了一個 docs文件夾。這個文件夾就是我們的文檔成果,進入該文件夾,打開頁面 template.html ,就可以看到我們今天的勞動成果啦!
? 曬一張成果圖,與大家共勉:
?
? 關于JSDuck的學習和實踐的分享,到這里就告一段落啦。希望對大家有所幫助,也隨時歡迎大家和筆者討論相關技術。
? 所有源碼下載地址:https://pan.baidu.com/s/1dE88lPZ
歡迎關注我的微信公眾號:
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/90722.html
摘要:語法父類名表示當前類繼承于哪個類的標簽。成員標簽成員標簽作用于類中的配置屬性函數(shù)事件。表明可被子類繼承,和一起使用。示例獲取圓的面積圓的半徑面積值作用于函數(shù),表明函數(shù)的標簽。作用于函數(shù),表明構(gòu)造函數(shù)參數(shù)的標簽,用法同。 字數(shù):3692字 閱讀時間:15分鐘 前言 ? 首先,咱們有一個前提,JSDuck對我們而言只是一個便于API查看的文檔化工具。因此,只要它能夠滿足我們文...
摘要:融合思路解決這個問題,有兩種思路。給我們帶來了以下新成員模塊服務指令篩選器和控制器。與其他類是通過類的名稱區(qū)分的,名稱統(tǒng)一以結(jié)尾。這種處理方式是一種折中方案,如果想要更加規(guī)范優(yōu)雅的話,建議使用自定義標簽來解決。 字數(shù):1568 閱讀時間:10分鐘 前言 ??前面,我們以一個實戰(zhàn)案例來詳細說明了如何在實際開發(fā)中使用JSDuck工具。但是,并不是所有的時候,代碼的封裝方式都受我們控制的。...
摘要:我們在對現(xiàn)在較主流的五個文檔工具分別作了調(diào)研和嘗試,得到結(jié)論如下工具優(yōu)點缺點提供了完整的模板開發(fā)事件觸發(fā)等接口,使用非常靈活。至此,的環(huán)境部署已經(jīng)全部完成了。 字數(shù):981 閱讀時間:5分鐘 選型依據(jù) ? 在經(jīng)歷了數(shù)個上線的項目之后,筆者所在的團隊已經(jīng)沉淀了一個相對穩(wěn)定版本的前端框架。因此,我們需要出具一套框架API文檔,以便公司其他成員的使用和框架的后期維護。我們在對...
摘要:本文比較了種較為主流的注釋文檔生成工具。應該說是非常適合開源項目多個作者共同維護的一個文檔工具。最后我選擇了作為文檔生成的工具。為了支持多種語言,它僅對注釋塊內(nèi)部的內(nèi)容進行解析。 最近隨著寫Node以及獨立的CommonJS模塊越來越多,我發(fā)現(xiàn)有一份好的文檔不僅可以幫助自己在應用這些接口的時候不至于迷糊,而且對于共同開發(fā)的情況下,能夠省去大量團隊的交流和Debug的時間。 本文比較了...
閱讀 2676·2023-04-25 20:19
閱讀 1930·2021-11-24 09:38
閱讀 1632·2021-11-16 11:44
閱讀 4341·2021-09-02 15:40
閱讀 1317·2019-08-30 15:55
閱讀 2022·2019-08-30 15:52
閱讀 3759·2019-08-29 17:20
閱讀 2247·2019-08-29 13:48