2015年10月26日 星期一

Angular 與 jQuery 的先後問題


近日在練習 Angular.js 的 ng-repeat 時,發現一個很怪的現象。程式碼如下:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" ng-app="NotesApp">
<head>
    <title></title>        
    <script src="//code.jquery.com/jquery-1.7.1.min.js"></script>
    <script src="js/angular.min.js" type="text/javascript"></script>    
 
</head>
<body  ng-controller="MainCtrl as ctrl">
    <table>
        <thead><tr><th>姓名</th></tr></thead>
        <tbody ng-repeat="note in ctrl.notes">
            <tr >
                <td>
                    <input type="text" id="txtName" value="{{note.UserName}}" ng-model="note.UserName" />
                </td>            
            </tr>
        </tbody>    
    </table>
    

    <script type="text/javascript">
        angular.module("NotesApp", [])
        .controller("MainCtrl", [function () {
            var self = this;
            self.notes = [
            { id: 1, UserName: 'Paladin' },
            { id: 2, UserName: 'Nikki' }
            ];

        } ]);
    </script>
</body>
</html>

理論上,畫面會根據 self.notes 的內容,於 <table> 裡面產生了兩筆資料。如畫面所示,的確也產生出兩筆資料。但有趣的是:
1.當我在 IE 瀏覽器使用中文輸入法輸入「中文」時,文字框的資料被清空了。
2.當我在 Chrome 瀏覽器使用中文輸入法輸入「中文」時,文字框的資料變成重複的「中文」。
3.當我在 FireFox 瀏覽器使用中文輸入法輸入「中文」時,文字框的資料是正常顯示。

就在我拜讀了 Angular 与 jQuery 加载顺序的问题 這篇文章後,發現,原來載入 jQuery.js 與 Angular.js 大有學問。當載入 Angular.js 後,Angular 會把 window.jQuery  擴展到自己的 jQLite。為了避免兩個 JS 出現相容性的問題,所以建議先載入 jQuery,再載入 Angular。

讀到這裡,似乎有摸到邊了,就算不完全懂,也似懂非懂。但猛然回頭,阿我不就是照他建議的順序在寫嗎,怎麼還是錯呢!於是,我很認命的去檢查 jQuery 的版本,透過一個版本一個版本去比對,終於找到端倪了。當 jQuery 版本引用到 1.9.0 以後,原先那奇怪的中文輸入問題就解決了。

最後,我在 Angular FAQ 的內容裡面看到一段話:

Does Angular use the jQuery library?

Yes, Angular can use jQuery if it's present in your app when the application is being
bootstrapped. If jQuery is not present in your script path, Angular falls back to its
own implementation of the subset of jQuery that we call jQLite.

Angular 1.3 only supports jQuery 2.1 or above. jQuery 1.7 and newer
might work correctly with Angular but we don't guarantee that.

也就是說,目前僅保證與 jQuery 的搭配是支援 jQuery 2.1 之後的版本。jQuery 1.7 或後面的新版本,則是不保證能正常執行。下次再遇到這種怪怪的問題時,不僅僅是引用的順序很重要,連版本也要注意了。雖然 Angular 建議我們稱這機會好好學 Angular 就好,不要再用 jQuery 這肥肥的程式了,但,這身上的包袱,可不是一時半刻就能抖乾淨的啊!

參考:
01:Angular 与 jQuery 加载顺序的问题
02:Angular FAQ

2015年10月21日 星期三

判斷瀏覽器是否有支援 required

在追查判斷瀏覽器是否有支援 Html5  required 功能時,看到網路上很多人都用了
if ($("<input />").prop("required") === undefined)
來判斷。我很好奇,$("<input />").prop("required"),這到底是什麼東西啊?

2015年4月7日 星期二

微妙的關係

jQuery 的選擇條件裡,存在著 child-selector 與 descendant-selector 的階層關係。

$("A > B") 表示著「父子關係」
在整個網頁的 DOM 裡找到所有的 B,再看 B的父親是不是 A,如果是,則保留;不是,則刪除,最後留下的就是我們所要的 B。

$("A    B") 表示著「子孫關係」
在整個網頁的 DOM 裡找到所有的 B,再用遞迴的方式去看看他的祖先是否有 A 存在,有的話就保留,沒有就剔除,最後留下的就是我們所要的 B。

由此可以看出,在「子孫關係」中,我們為了要能夠判斷祖先是否存在我們所指定的項目,所以需要透過遞迴的方式不斷地往上去尋找。而找尋的時間,就會隨著 DOM 階層的複雜而增加。

針對效能的考量,當已經知道可以透過「父子關係」就能找出想要的資料時,就該使用「父子關係」,而避免使用「子孫關係」。

參考:
01:Child Selector
02:Descendant Selector
03:網站開發新路線:jQuery核心詳解與實踐應用