【Zepto源码】前端开发 CSS方法

html5前端开发国籍省份输入|前端开发比java简单吗?|extjs开发前端代码

css方法,顾名思义是操作样式的。其实也就是操作style的。
对于style这个东西要说的很多,恐怕很多书籍都拿出一章来说它。
不过本文既然分析此方法,稍微说几句关于style的操作。

第一个问题,具体样式的获取。
比如我要获取width具体样式值,可以用dom.style.width来做,例子如下:
html 代码

<div style=”width:200px;”></div>
<script>
    var div = document.querySelector(‘div’);
    alert(div.style.width); // “200px”
</script>

平常我们不会把样式代码,写进html中的,换成如下的方式:
html 代码

<style>
    div {
        width: 200px;
    }
</style>
<div></div>
<script>
    var div = document.querySelector(‘div’);
    alert(div.style.width); //””
</script>

而此时弹出是的空串,如果我们要得到”200px”时,我们需要得到的style,应该计算后的style,即getComputedStyle。
然后进一步获取其width值,即可做到,例如:
html 代码

<style>
    div {
        width: 200px;
    }
</style>
<div></div>
<script>
    var div = document.querySelector(‘div’);
    var width = getComputedStyle(div, “”).getPropertyValue(‘width’);
    alert(width);
</script>

什么叫计算后的样式?
百度吧,应该是该样式的所有样式组合的计算结果。包括样式表、style特性,以及脚本对style属性的各种操作后的style。

除了写成div.style.width之外,也可以写成div.style[‘width’]。
如果要获取background-color的话,不能写成div.style.background-color,因为连字符“-”,被当作减号来处理了。
而要写成div.style.backgroundColor,或者div.style[‘backgroundColor’],或者div.style[‘background-color’]。
而要使用计算后的样式话,要使用’background-color’。

另外,还有一种获取方式,div.style.getProperty(‘background-color’)

第二个问题,样式的设置。
我们可以使用
div.style.backgroundColor = “red”
来设置背景颜色,这是我们熟悉的方式。
或者div.style.setProperty(‘background-color’,’green’)
也可以通过对div.style.cssText进行操作,来设置背景颜色,比如:
html 代码

<style>
    div {
        height: 100px;
    }
</style>
<div></div>
<script>
    var div = document.querySelector(‘div’);
    div.style.cssText += “;background-color:red;”;
</script>

第三个问题,删除相应的样式。
可以使用
div.style.removeProperty(‘background-color’)
可以总结一下,只要是用函数的方式,我们都传连字符形式的。

根据这几个问题,我们可能会用到两个函数,
驼峰化的样式属性和连字符化的样式属性互转的情形。
驼峰化函数之前已分析过:
[quote]var cameLize = function(str) {
return str.replace(/-+(.)?/g, function(match, chr) {
return chr ? chr.toUpperCase() : “”;
});
};[/quote]
即给”background-color”,能得到”backgroundColor”
反过来的连字符化:
[quote]function dasherize(str) {
return str.replace(/::/g, ‘/’) // 把::变成/
.replace(/([A-Z]+)([A-Z][a-z])/g, ‘$1$2′) // 再连续的大写字母的最后一个之前插入
.replace(/([a-z\d])([A-Z])/g, ‘$1$2′) //在小写字母(或者数字)与大写字母之间插入
.replace(/_/g, ‘-‘) //把_替换成-
.toLowerCase(); //全部小写化
}[/quote]
为什么有第一步,个人不清楚,
对于正则不好的同学,可以跟踪一下每一步的结果。
javascript 代码

function dasherize(str) {
    console.log(str)
    str = str.replace(/::/g, ‘/’);
    console.log(str)
    str = str.replace(/([A-Z]+)([A-Z][a-z])/g, ‘$1_$2’);
    console.log(str)
    str = str.replace(/([a-z\d])([A-Z])/g, ‘$1_$2’);
    console.log(str)
    str = str.replace(/_/g, ‘-‘);
    console.log(str)
    str = str.toLowerCase();
    console.log(str)
    return str;
}
dasherize(‘::aaABBcdefH1g3Ggg’);
// “::aaABBcdefH1g3Ggg”
// “/aaABBcdefH1g3Ggg”
// “/aaAB_BcdefH1g3Ggg”
// “/aa_AB_Bcdef_H1g3_Ggg”
// “/aa-AB-Bcdef-H1g3-Ggg”
// “/aa-ab-bcdef-h1g3-ggg”
dasherize(‘backgroundColor’);
// “backgroundColor”
// “backgroundColor”
// “backgroundColor”
// “background_Color”
// “background-Color”
// “background-color”

有了以上铺垫我们可以分析源码了。
具体思路是跟据不同的使用情形,写出不同的代码。
最后进行合并,也就是参数重载。这样便于分析。

情形1:$(‘div’).css(‘background-color’)
一个参数是读取。根据zepto的设计原则(取,只取一个,设,设置所有)我们可以简单写成如下的代码:
[quote]$.fn.css = function(property) {
var element = this[0];
if (!element) return;
return element.style[camelize(property)] || getComputedStyle(element).getPropertyValue(property);
};[/quote]
优先调用style来获取,没有再获取计算后的style里的相应样式。
从代码中可见,要求我们传的参数是连字符化的。

情形2:$(‘div’).css([‘width’, ‘background-color’])
代码如下:
[quote]$.fn.css = function(property) {
var element = this[0];
if (isArray(property)) {
if (!element) return;
var props = {};
var computedStyle = getComputedStyle(element, “”);
$.each(property, function(, prop) {
props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop));
});
return props;
}
};[/quote]
其中isArray是用来判断是否为数组。返回的是个对象,key就是数组property中的元素。
代码中有趣的一点是,each工具方法的回调函数的一个参数用了“
”,没用i来表示index。这样是为了告诉读者,这里不会用到第一个参数的。也就是用它来占个位置。技能get!

情形3:$(‘div’).css(‘background-color’, ‘red’)
设置样式。
源码实现使用的是cssText来做的。
实现如下:
[quote]$.fn.css = function(property, value) {
var css = dasherize(property) + “:” + value;
return this.each(function() {
this.style.cssText += ‘;’ + css;
});
};[/quote]
从代码可以看出,“设”时property可以为驼峰式的。但是为了和“取”保持一致,我们最好一直用连字符形式的。
源码中考虑到,还考虑到两种情形。
1.如果value值为false,””,null和undefined时那么就当作是删除该样式属性了,比如$(‘div’).css(‘background-color’,null),其实现可以改成如下形式:
[quote]$.fn.css = function(property, value) {
var css = “”;
if (!value && value !== 0) {
this.each(function() {
this.style.removeProperty(dasherize(property));
})
} else {
css = dasherize(property) + “:” + value;
}
return this.each(function() {
this.style.cssText += ‘;’ + css;
});
};[/quote]

2.另外一种情况是,像$(‘div’).css(‘width’, 20),真正的意思表达的是$(‘div’).css(‘width’, ’20px’)。
这样便捷写法,css也是支持的。因此代码变成:
[quote]$.fn.css = function(property, value) {
var css = dasherize(property) + “:” + maybeAddPx(property, value);
return this.each(function() {
this.style.cssText += ‘;’ + css;
});
};[/quote]
其中maybeAddPx是一个内部函数,来维护是否给value添加单位’px’,实现如下:
[quote]function maybeAddPx(name, value) {
return (typeof value == “number” && !cssNumber[dasherize(name)]) ? value + “px” : value;
}[/quote]
只有为数字的情形下,才考虑要不要加’px’。当然也不是任何属性都可以加这个单位的。cssNumber对象表示那些要排除掉的:
[quote]var cssNumber = {
‘column-count’: 1,
‘columns’: 1,
‘font-weight’: 1,
‘line-height’: 1,
‘opacity’: 1,
‘z-index’: 1,
‘zoom’: 1
};[/quote]

情形4: $(‘div’).css({‘width’: 200})
设置的另外一种方式,有了情形3的实现,情形4就好做了。
[quote]$.fn.css = function(property, value) {
var css = “”;
for (key in property) {
if (!property[key] && property[key] !== 0) {
this.each(function() {
this.style.removeProperty(dasherize(key));
});
} else {
css += dasherize(key) + ‘:’ + maybeAddPx(key, property[key]) + ‘;’
}
}
return this.each(function() {
this.style.cssText += ‘;’ + css;
});
};[/quote]

完整实现,只需要梳理一下各种if:
[quote]$.fn.css = function(property, value) {
if (arguments.length < 2) {
var element = this[0];
if (typeof property == ‘string’) {
if (!element) return;
return element.style[camelize(property)] || getComputedStyle(element,””).getPropertyValue(property)
} else if (isArray(property)) {
if (!element) return;
var props = {};
var computedStyle = getComputedStyle(element, “”);
$.each(property, function(_, prop) {
props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop));
});
return props;
}
}
var css = “”;
if (type(property) == ‘string’) {
if (!value && value !== 0) {
this.each(function() {
this.style.removeProperty(dasherize(property));
})
} else {
css = dasherize(property) + “:” + maybeAddPx(property, value);
}
} else {
for (key in property) {
if (!property[key] && property[key] !== 0) {
this.each(function() {
this.style.removeProperty(dasherize(key));
});
} else {
css += dasherize(key) + ‘:’ + maybeAddPx(key, property[key]) + ‘;’
}
}
}
return this.each(function() {
this.style.cssText += ‘;’ + css;
});
};[/quote]

逐步分解后来看,还不是太复杂。
如果第一眼,直接看源码的话,可能需要考虑半天。

intellij idea 前端开发|前端开发video用法|html5前端开发环境

» 本文来自:前端开发者 » 《【Zepto源码】前端开发 CSS方法》
» 本文链接地址:https://www.rokub.com/3900.html
» 您也可以订阅本站:https://www.rokub.com
赞(0)
64K

评论 抢沙发

评论前必须登录!