據說每個大牛、小牛都應該有自己的庫——DOM處理續

謙行發表於2013-09-14

在上篇據說每個大牛、小牛都應該有自己的庫——DOM處理最後剩下attr()和css()方法沒有處理,因為這兩個方法當時並不自計劃中,是寫著寫著突然想到的,一時間沒有特別好的思路,當時已十一點多了,就去睡了。沒想到啊沒想到接下來的一星期簡直是噩夢,每天加班回家都十一點,今天有時間趕緊補上。

property與attribute

之前說了這兩個方法是仿照jQuery的,看了一下jQuery的原始碼,發現從1.6後jQuery多了一個prop()方法,做的功能卻和attr()很相似,看了很多資料才明白prop是在解決什麼問題。

property和attribute都可以翻譯為屬性,不過為了區別一般把property翻譯為特性,而在JavaScript中,property和attribute的區別不止這麼簡單。setAttribute是為DOM節點設定/新增屬性的標準方法,我們一般會這麼用

var e = document.getElementById('ck');
        e.setAttribute('title', 'test');

也可以這麼用

var e = document.getElementById('ck');
        e.title = 'test';

無論怎麼設,在讀取的時候這麼用

alert(e.getAttribute('title'));
        alert(e.title);

對attribute設定/讀取值使用setAttribute/getAttribute,property使用.操作符,兩種用法看似毫無區別,但是我們也經常設定元素的class,想要得到預期結果得這麼寫

e.setAttribute('class', 'test');
        e.className = 'test';

同樣都是對class操作,使用attribute的key是class,property卻是className,其讀取的結果也不一定相同(input 的checkbox)

console.log(e.getAttribute('checked')); //checked
console.log(e.checked); //true

DOM物件大部分的內建property都有對應的名字的attribute(名字也可能不同,比如上面的class),對於自定義的屬性雙發互不干擾(IE9以下版本還是共享的)

e.setAttribute('customizeProperty', 'attribute');
        e.customizeProperty = 'property';
        console.log(e.getAttribute('customizeProperty')); //attribute 
        console.log(e.customizeProperty); //property

image

看起來似乎很清楚了,看個例子

<input id="ck" type="checkbox" checked="checked" />
    <script type="text/javascript">
        var e = document.getElementById('ck');
        
        console.log(e.getAttribute('checked')); //checked
        console.log(e.checked); //true

        e.checked = false;
        console.log(e.getAttribute('checked')); //checked
        console.log(e.checked); //false

        e.setAttribute('checked', 'checked');
        console.log(e.getAttribute('checked')); //checked
        console.log(e.checked); //false

</script>

這是怎麼個情況,不是內建屬性是共享的嗎,怎麼互不干擾了?這是因為一些Boolean型別的屬性(如checked, selected, disabled等)比較特殊,其attribute只保留初始值(預設值), property才是當前最新的狀態值。一個預設勾選的checkbox,當在頁面去除勾選的時候,checked這個property已由true變為false,而checked這個attribute仍然保持“checked”這個初始值。

attr()

這都和attr()有神馬關係,說上面的原因是既然瞭解了property和attribute的不同,那麼自己的庫乾脆也像jQuery把property和attribute分開處理。自己寫了很多,總是有這樣那樣的問題,看到了大神John Resig的處理方法後,豁然開朗,這兩個方法是可以寫成結合體的,無恥的簡單改造了一下抄過來,註釋寫的都這麼經典沒捨得刪

attr: function (elem, name, value) {
                    // Are we setting a value?
                    if (typeof name == 'object') {
                        for (n in name) {
                            attr(elem, n, name[n]);
                        }
                    }
                    else if (value !== undefined) {
                        // Make sure the element has the ability to set an attribute
                        if (typeof elem.setAttribute !== "undefined") {
                            // If the user is setting the value to false
                            if (value === false) {
                                // Completely remove the attribute
                                elem.removeAttribute(name);

                                // Otherwise set the attribute value
                            } else {
                                // If the user is setting the value to true,
                                // Set it equal to the name of the attribute
                                // (handles boolean attributes nicely)
                                elem.setAttribute(name, value === true ? name : value);
                            }

                            // If it doesn't, then we're likely dealing with window or document
                            // (or some other object entirely)
                        } else {
                            elem[name] = value;
                        }

                        // Otherwise we're getting an attribute value
                        // Check to see if the appropriate method exists
                        // Also don't use getAttribute if a boolean property exists
                    } else if (typeof elem.getAttribute !== "undefined" && typeof elem[name] !== "boolean") {
                        return elem.getAttribute(name);

                        // If no getAttribute method is present, or if we
                        // wish to access the boolean property instead of the
                        // attribute, then we fallback to the DOM object property
                    } else {
                        return elem[name];
                    }
                }

css()

css()方法就寫不了jQuery那麼強大了,基本沒有做錯誤處理,所以使用的時候必須保證傳入的屬性名稱和值是正確的,同時只能傳入簡單的屬性名,而不能是-moz-等類似的

css:function(ele,name,value){
                    if(typeof name=='object'){
                        for(n in name){
                            ssLib.css(ele,n,name[n]);
                        }
                    }else if(typeof value!='undefined'){
                        ele.style[_parseStyleName(name)]=value;
                    }else{
                        return   ele.style[_parseStyleName(name)];
                    }
                }

 

參考

http://ejohn.org/blog/jquery-16-and-attr/(大神John Resig的部落格)

相關文章