做者:Icarus
原文連接:手把手帶你用原生js實現css屬性的set和getjavascript
上一篇博文介紹了getComputedStyle方法,接下來,咱們就來實現一個簡易版的小插件,可以在不借助jQuery的狀況下實現css屬性的獲取和設置。css
首先建立一個 css-tool.js
文件,一開始他是這個樣子的:html
;(function (window,undefined) {
"use strict";
var cssTool = function () {
return new cssTool.prototype.init();
}
cssTool.prototype = {
init: function() {
console.log('init success');
return this;
},
}
cssTool.prototype.init.prototype = cssTool.prototype;
// 暴露接口
window.cssTool = cssTool;
})(window);複製代碼
全局做用域能夠看做是一棟公寓樓,咱們建立一個當即執行的匿名函數,至關因而公寓樓中的一間公寓,咱們在屋子裏作的事情就都是隱祕的,也就是起到隔離做用域的做用,避免和外部變量產生衝突。把 window
做爲參數拿到屋子裏來,之後就不用再重複去外面找 window
來用。最前面的分號是爲了保證在文件合併壓縮後不產生語法錯誤。 undefined
在老版本瀏覽器中不被支持,所以考慮到兼容性添加一個形參。java
咱們建立了一個叫 cssTool
的私有方法,至關於咱們在屋子裏找了一個小房間來放 get
和 set
等方法。接下來咱們在原型上新增一個 init
方法,用於初始化。以後咱們仿照 jQuery
的方式,將init
的 prototype
指向 cssTool
的 prototype
,這樣咱們在用init
做爲構造函數創造實例時,可使插件擁有兩種調用方式:git
var ct = new cssTool()
構建 cssTool
實例cssTool()
,同樣返回 cssTool
實例window.getComputedStyle(elem,null).getPropertyValue(attr)複製代碼
elem.currentStyle.getAttribute(camelCase(attr))複製代碼
對 currentStyle
來講,在IE6瀏覽器中他很專注,只喜歡以駝峯命名法命名的變量,而IE78中就有點朝秦暮楚,駝峯命名法和中間帶'-'的都照單全收,爲了兼容和操做的簡便,咱們統一轉換爲駝峯命名法。github
/** * 駝峯命名法轉換,IE678使用 * font-size --> fontSize * @param {String} attr * @param {String} match 匹配到的字符串,如-c * @param {String} originText (\w)是一個捕獲,這裏是捕獲到的字符,如c * @return 返回駝峯命名方式的css屬性名 */
function camelCase (attr){
return attr.replace(/\-(\w)/g, function (match,originText) {
return originText.toUpperCase();
});
}複製代碼
IE678的透明度是經過 filter:alpha(opacity=0)
來設置的,咱們利用正則表達式匹配到此時透明度的值,因爲此時獲得的是0-100之間的數值,因此須要換算爲咱們常見的0-1的形式。正則表達式
/** * IE678下獲取透明度的值 * @param elem 獲取值的 dom * @return {Number} 透明度的值,默認爲1 * IE678下設置透明度 filter: alpha(opacity=0) 取值爲0-100 */
function getFilter(elem) {
var _filter = elem.currentStyle.getAttribute('filter').match(/alpha\(opacity=(.*)\)/i);
var value = parseFloat(_filter[1]);
if(!isNaN(value)){
// 轉化爲0-1
return value ? value/100 : 0;
}
return 1;
}複製代碼
上一篇博客中提到,因爲 float
是 ECMAScript 的一個保留字。因此在各瀏覽器中都會有代替的寫法,好比說在現代瀏覽器中爲 cssFloat
,而在 IE678 中爲 styleFloat
。經測試,在現代瀏覽器中直接使用 getPropertyValue("float")
也能夠獲取到 float
的值。而 IE678 則不行,因此針對 float
,須要簡單的hack。瀏覽器
對於一個沒有設定高寬的元素而言,在 IE678 下直接獲取獲得的值是 auto
。而現代瀏覽器會直接返回它的 px 值,咱們的目標就是在 IE 下也返回 px 值。dom
// 直接獲取外部樣式表未設置的 width 和 height 返回值爲 auto
// 爲了獲取精確的 px 值,使用 getBoundingClientRect 方法
// getBoundingClientRect 能夠得到元素四個點相對於文檔視圖左上角
// 的 top、left、bottom、right值,進行簡單計算便可
var condition = attr === 'width'
|| attr === 'height'
&& elem.currentStyle[attr] === 'auto';
if(condition){
var clientRect = elem.getBoundingClientRect();
return (attr === 'width' ?
clientRect.right - clientRect.left :
clientRect.bottom - clientRect.top
) + 'px';
}複製代碼
set 方法相較於 get 方法要簡便的多,由於咱們有 cssText
這個跨越 IE6+ 和現代瀏覽器的神器。
經過elem.style.cssText
能夠對元素的樣式進行讀寫,實際上操做的是 html 標籤上的 style
屬性的值。所以不能直接對其賦值,否則就把整個 style
屬性的值給覆蓋掉了。咱們採用累加的方式來修改屬性。
另外,在IE瀏覽器還有個小坑,若是 cssText 不爲空,返回值最後一個分號會被刪掉,所以咱們須要在累加的屬性前加上一個分號。函數
/** * 設置元素css樣式值 * @param elem 設置值的dom元素 * @param {String} attr 設置樣式名稱,如font-size * @param {String} value 設置樣式的值,如16px */
set: function (elem, attr, value){
// IE78 設置透明度需特殊處理
if(attr === 'opacity'){
// 針對 IE7 的 hack
// filter 濾鏡要求 hasLFooout=true 才能執行
// IE瀏覽器且 hasLFooout=false 時執行
if(!!elem.currentStyle && !elem.currentStyle.hasLFooout){
elem.style.zoom = 1;
attr = 'filter';
value = 'alpha(opacity=' + value * 100 + ')';
}
}
// 通用方式
elem.style.cssText += ';' + (attr + ':' + value) + ';';
}複製代碼
var Foo = function() {
return new Foo.prototype.init();
}
Foo.prototype = {
init: function() {
this.age = 18;
return this;
},
age: 20
}
console.log(Foo().age); // 18
console.log(Foo.prototype.age); // 20複製代碼
var Foo = function() {
return Foo.prototype.init();
}
Foo.prototype = {
init: function() {
this.age = 18;
return this;
},
age: 20
}
console.log(Foo().age); // 18
console.log(Foo.prototype.age); // 18複製代碼
使用 new 操做符時,是把 init
當成構造函數來調用,在 init
內部會建立一個隱式對象並用 this
指向它,此時的 this.age=18
表示在這個隱式對象上增長一個 age 屬性,最後 return this
不是必需的,構造函數默認會返回 this
。此時Foo.prototype.age
不受影響。
當不使用 new 操做符時,至關於一個普通對象上的函數調用,this
指向了 init
所屬的對象,即 Foo.prototype
,this.age=18
至關於對 Foo.prototype.age
賦值,和使用 new 操做符是有本質區別的。
到這裏,教程也就要告一段落了。一個 jQuery 中常見的 css()
方法背後涵蓋了很是多的知識點,跨瀏覽器的兼容性也是咱們這次討論的重點,此次只是實現了一個很是簡易的 css 操做插件。學問尚淺,若是有不清楚或者有錯誤的地方,歡迎各位留言或者提issue來幫助我改進這個小插件。
最後,完整的項目地址:github.com/xdlrt/css-t…求一波star~