如何調試Dojo

 

Dojo是非常小、非常快速的,並且使用了非常聰明的技巧來節省內存和時間. 不足的是:Dojo並不大量的跟蹤程序錯誤,因爲這會使代碼變得臃腫,速度變得很慢. 剛開始接觸的時候,如果你的代碼運作不正常,返回的錯誤可能會令你非常困惑.

不用擔心! 這裏提供的一些技巧,會使你成爲一個自信、成功的程序調試員. 提前瞭解這些技巧會讓你學習Dojo變得更加容易.

使用 Firebug 或者是 Firebug Lite

我們不得不強調一下. Firebug, 一個開源的Firefox測試插件, 非常適用於JavaScript, HTML 和 CSS 的調試. 你可以從 Firebug 網站 下載.

如果你不是Firefox 使用者? 你可以考慮轉換過來用Firefox,至少在開發Dojo程序的時候使用Firefox. 跨平臺運行是Dojo的一個優點. 所以你使用的越充分,你的代碼可遷移性就越強,你選擇那個瀏覽器也就無所謂了.

還不相信嗎? 沒問題. 如果你使用 Internet Explorer 或者 Safari, 你可以使用跟Dojo捆綁在一起的 Firebug Lite library. 它提供了一些Firebug的調試日誌和命令行屬性. 雖然不是非常全面,但也是一個相當好的替代方法.

要使用 Firebug Lite, 你需要設置 isDebug 參數,如下:

<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0//dojo/dojo.js"
djConfig=
"parseOnLoad: true, isDebug: true">
</script>

這個參數對已經啓用Firebug的Firefox 是不起作用的. 所以包含這個參數只是使你可以在 IE, Safari, 和沒有安裝Firebug的 Firefox 上調試Dojo程序.

dojo.require錯誤和Firebug控制檯

下面的代碼有一個非常小的錯誤:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Fix me!</title>
<style type="text/css">
@import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
@import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
</style>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.js"
djConfig=
"parseOnLoad: true, isDebug: true">
</script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.Textbox");
</script>
</head>
<body class="tundra">
<form>
What's the 411? <input type="text" size="20" name="info" dojoType="dijit.form.TextBox"
trim="true" propercase="true" />
<br>
</body>
</html>

沒有Firebug, 這短代碼會產生一個無用的彈出窗口(IE) 或者 什麼也沒顯示 (Firefox). 看起來textbox是肯定不對的. 你輸入一個小寫的名稱並引起了錯誤... 正確的寫法是第一個字母大寫嗎? 也不是.

使用Firebug,錯誤是非常容易跟蹤的. 首先, 右下角會有一個提示.

debugging1.png

點擊"1 Error" ,Firebug 控制檯會彈出:

debugging2.png

回過頭來看一下代碼, 你注意到dojo.require中 "Textbox" 的大小寫錯了. 這是一個常見的錯誤, 但也很容易改正. 忘記 dojo.require, 或者 dojoType 屬性的類拼寫錯誤也是常見錯誤. 無論是怎樣的情況, Firebug 都可以直接指出來.

Firebug Lite 提供了一個相似的控制檯, 但它是在瀏覽器窗口的底部顯示. 要把它關掉,你需要把 isDebug 標記設爲 false,並重新執行頁面.

Dojo/Method 和 Dojo/Event 代碼中錯誤

下面的代碼存在一個錯誤:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Fix me!</title>
<style type="text/css">
@import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
@import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
</style>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
djConfig="parseOnLoad: true"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.Button");
var newWidth = '200px';
</script>
</head>
<body class="tundra">
<div dojoType="dijit.form.Button">
Click to break!
<script type="dojo/event" event="onClick">
this.domNode.style.width = dojo.newWidth;
</script>
</div>
</html>

但是你看控制檯的時候, 並沒有明顯的錯誤. 在使用其他語言的時候,可以使用調試器爲"this.domNode"行設置一個斷點(breakpoint). Firebug調試器同樣也可以做到 , 這段代碼中我們不使用. 因爲"dojo/event" 、 "dojo/method" 這兩種腳本類型的編譯和 "text/javascript" 是不同的. 但這裏還有兩種方法可以選擇.

方法 1: 調試日誌

第一種方法是調試日誌,如果你用過像log4j這樣的日誌工具就會覺得非常熟悉. 思路就通過寫日誌信息,輸出變量的值和執行的代碼.

爲什麼不用alert()呢 ? JavaScript alert() 是一個非常受歡迎的。值得信賴的調試工具,但會引起下面的問題:

  • 如果有很多錯誤提示,不斷的點擊[OK]是非常煩人的
  • 太多的文字輸出會使提示窗的大小比平面窗口還大
  • 程序發佈的時候需要手工刪除所有的 alert()
  • alert() 如果放在一個死循環中,會一直的彈出窗口,直到關閉瀏覽器進程
  • 輸出對象內容和數組不方便

很明顯,alert並不夠強大. 在 Dojo 日誌中, 你可以把錯誤嚴重程度和信息提示聯繫起來,就像log4j一樣. 下面的代碼舉例說明了5個等級的調試錯誤:

console.log("Nothing happening");
console.debug("Checking to make sure nothing happened");
console.info("Something might happen.");
console.warn("Something happened, but it's no big deal.");
console.error("Cough cough!");

在Firebug 控制檯中, 信息顯示如下:

firebug_logging.png

在IE中, 顯示如下:

firebug_ie_capture.png

另一個方法, console.dir() 把變量的內容全部輸出到屏幕. console.log 處理字符串和整型數據比較有優勢,console.dir 適合處理更復雜的變量 - 對象, 數組, 對象數組, 或者其它的. 例如:

console.dir([
{attribute: "last_name", sortDescending: true},
{attribute: "last_name", sortDescending: true}
])
;

輸出結果:

firebug_logging2.png

所以在以上的例子中,我們寫入:

console.debug("dojo.newWidth is" + dojo.newWidth);
this.domNode.style.width = dojo.newWidth;

運行代碼,我們會發現dojo.newWidth沒有定義. 是拼寫錯了嗎?要快速找到這個問題, 我們把代碼修改爲:

console.dir("dojo is" + dojo);
this.domNode.style.width = dojo.newWidth;

很快我們會發現dojo中並沒有newWidth這個屬性. 最終,我們找到了代碼的錯誤並將這一行右邊的代碼修改爲"newWidth." 問題解決.

方法 2: The "debugger" Statement

另外,也可以爲代碼設置一個"簡單的斷點". 就是隻增加一個" debugger; "聲明, 這是一個合法的 JavaScript保留字(預定義字).

debugger;
this.domNode.style.width = dojo.newWidth;

這句代碼停止了代碼的運行,並打開了一個Firebug 命令窗口. 這表明代碼是在這個地方停止的 ...

debugging4.png

這是運行 dojo/event 代碼的效果. 斷點好像並沒有產生作用.

點開 Console 標籤,檢查變量和運行的 JavaScript代碼.我們看一下 dojo.newWidth 屬性, 沒有任何東西. 但 "dojo" 是有的,我們可以通過 console.dir(dojo)來查看. 所有方法1的日誌屬性都在這裏列出來了.

debugging3.png

跟蹤 dojo.require , 需要使用本地服務器上的Dojo

上面的代碼已經正常運行了,我們調整一下,把按鈕( button )設爲藍色( blue):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Fix me!</title>
<style type="text/css">
@import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
@import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
</style>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
djConfig=
"parseOnLoad: true">
</script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.Button");
</script>
</head>
<body class="tundra">
<div dojoType="dijit.form.Button">
Click to break!
<script type="dojo/event" event="onClick">
this.domNode.style.backgroundColor = dojo.Color.named.aliceblue;
</script>
</div>

</html>

查看控制檯 ... 沒有顯示錯誤. 但dojo.Color.named.aliceblue 是有點值得懷疑的. 我們都知道 dojo.colors 需要被加載, 但我們不確定是不是 dijit.form.Button 已經包含了這個加載。

當你使用本地Dojo的時候,可以順利的把它找出來. CDN Dojo 對它加載的模塊是保持沉默的. 本地 Dojo 則是非常�嗦的. 所以, 確定在服務器目錄(underneath /dojoroot)安裝了Dojo包, 再修改一下下面的代碼:

<style type="text/css">
@import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
@import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
</style>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
djConfig=
"parseOnLoad: true">
</script>
修改後代碼:
<style type="text/css">
@import "dojoroot/dijit/themes/tundra/tundra.css";
@import "dojoroot/dojo/resources/dojo.css"
</style>
<script type="text/javascript" src="dojoroot/dojo/dojo.xd.js"
djConfig=
"parseOnLoad: true">
</script>

 

控制檯會顯示:

debugging5.png

你可以看到所有加載的Dojo 核心 和 Dijit 組件。 很明顯, dojo.colors 不在裏面, 所以我們要增加一個 dojo.require。

還是不對 ... 檢查DOM

如果你的問題還沒有解決,那真的很不幸.發生樣式錯誤的時候,我們就需要使用 Firebug的 DOM 檢查器了.

  • 它顯示了當前的 DOM 結構, 並不是剛開始的時候加載的
  • 你可以查看每個節點的DOM屬性- 那就是, 按 Inspect 並指向目標

我們點擊 Inspect ,並指向屏幕中的按鈕

debugging6.png

控制檯的右面顯示了樣式,以及這個類使用的樣式. 帶中劃線的是無用的樣式. 非常不錯!

Debugging External Classes With debugAtAllCosts

dojo/method 和 dojo/event 腳本適合用於簡短、不重複利用的代碼片段. 但如果你開始構建重複利用的組件, 你需要把代碼保存到Dojo聲明的類中. 好處就是這種方法你用的越多,調試起來就越容易.

下面是個一個 HTML 代碼和一個可重複利用的Dojo部件(widget):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Goolica Tax Form</title>
<style type="text/css">
@import "/dojoroot/dijit/themes/tundra/tundra.css";
@import "/dojoroot/dojo/resources/dojo.css"
</style>
<script type="text/javascript" src="/dojoroot/dojo/dojo.js"
djConfig=
"parseOnLoad: true">
</script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dojobook.online-book.debugging.BuggyWidget");
</script>
</head>
<body class="tundra">
<div dojoType="dojobook.online-book.debugging.BuggyWidget"></div>
</body>
</html>
dojo.provide("dojobook.online-book.debugging.BuggyWidget");
dojo.require("dijit._Widget");
dojo.declare(
"dojobook.online-book.debugging.BuggyWidget",
[dijit._Widget],
{
postCreate: function() {
dojo.nonExistentMethod();
}
})
;

運行這段代碼,你會發現一個錯誤,但是顯示的錯誤位置是不對的:

debugging8.png

但當我們把 debugAtAllCosts 標記設置爲 true:

<script type="text/javascript" src="/dojoroot/dojo/dojo.js"
djConfig=
"parseOnLoad: true, debugAtAllCosts: true">
</script>

錯誤顯示的位置就正確了:

debugging7.png

重要提示: 你一定要在發佈的程序產品中把 debugAtAllCosts 去掉. 它會使客戶端的運行變慢. 相比於直接手工添加和刪除, 我更喜歡用服務器語言(如PHp)來處理這個工作:

<?php
$djConfig = $inProduction ? "parseOnLoad: true" : "parseOnLoad: true, debugAtAllCosts: true";
$loadLocation = $inProduction ? "http://o.aolcdn.com/dojo/1.0.0" : "/dojoroot";
$useXd = $inProduction ? ".xd" : "";
?>
<style type="text/css">
@import "<?= $loadLocation ?>/dijit/themes/tundra/tundra.css";
@import "<?= $loadLocation ?>/dojo/resources/dojo.css"
</style>
<script type="text/javascript" src="<?= $loadLocation ?>/dojo/dojo<?= $useXd ?>.js"
djConfig="<?= $djConfig ?>"></script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章