【茶包射手日記】KO 3.3升級不相容之偵錯練習
0 |
專案由Knockout.js 3.2升級到3.3後,某個網頁原本使用<!-- ko if … -->切換元素顯示的功能失效,抓了一陣子才發現原來是寫法有誤,原本該寫<!-- ko if: someFalg -->卻寫成<!-- ko if (someFlag) -->,修改為<!-- ko if: someFlag -->問題即告排除。
但這激起我的好奇心,想找出3.2到3.3造成此一行為差異的根源改變。(其實是手癢想練習JavaScript偵錯技巧)
用一段小程式重現問題:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>if/ifnot Test</title>
</head>
<body>
<input type="checkbox" data-bind="checked: Flag" />
Flag = <span data-bind="text: Flag"></span>
<div>
<!-- ko if (Flag) -->
Flag On
<!-- /ko -->
<!-- ko ifnot (Flag) -->
Flag Off
<!-- /ko -->
</div>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script>
ko.applyBindings({ Flag: ko.observable(true) });
</script>
</body>
</html>
測試結果,使用KO 3.2可以順利切換Flag On及Flag Off,使用KO 3.3則if/ifnot失效,Flag On及Flag Off永遠出現。
開啟F12偵錯,設定中斷點,一步一步挖進去,終於找出差異禍首:
KO 3.3調整了內部函式parseObjectLiteral()的邏輯,這個函式負責分析縏結字串轉為Key/Value配對,以找出對應的繫結處理器,例如:"text: Prop"會轉成Key="text",Value="Prop",代表要使用text繫結,繫結對象是Prop。
設定程式中斷點,直接呼叫parseObjectLiteral()進行測試。程式誤寫的非典型繫結字串"if(Flag)"(正確應為"if:Flag"),使用KO 3.2的parseObjectLiteral()還是可以正確解析出Key="if", Value="Flag"。
到了KO 3.3,因parseObjectLiteral()內部有個if條件修改,"if(Flag)"已不再視為有效,會被歸為unknown。至於if:Flag在KO 3.2跟3.3都可正確解析。
成功鎖定目標,偵錯練習完畢。
Comments
Be the first to post a comment