最近还在翻jQuery的源码。 乍一看源码,一头雾水,毫无头绪。 当我真正静下心来仔细看的时候,文笔真的很精致,让你感受到代码的美。
它具有结构清晰、高内聚、低耦合、优异的性能和方便的扩展性,在浏览器兼容性(功能缺陷,逐步完善)、高贵的处理能力、Ajax等方面有贴心强大的定制功能。 惊人。
另外,阅读源码让我接触到了很多底层知识。 对原生JS、框架设计、代码优化都有了新的认识,接下来会写一系列关于jQuery分析的文章。
我在github上对jQuery源码的全文注释,有兴趣的可以看一下。 jQueryv1.10.2源代码注释。
言归正传,这篇文章讲的是原生JS获取和设置元素最终样式的技巧。 也许我们已经习惯了使用框架。 以jQuery为例,使用.css()套接字可以轻松满足我们的要求。 看明天要讲的window.getCompulatedStyle,就像我刚接触JS时看到document.getElementById一样。 不过大家不要惊慌,我觉得如果我们不仅仅想做一个能吃很多东西的后端,越是底层的东西,如果能理解的话,就越能提高。
getCompatedStyle 和 getPropertyValue
什么是 getCompatedStyle? DOM 中的 getComputedStyle 方法可用于获取元素中所有可用 css 属性的列表,并将其作为链表返回,但它是只读的。 在 IE678 中,改用 currentStyle。
假设我们页面中有一个id为id的元素,那么使用getCompulatedStyle获取元素样式如右图所示:
//句型:
//在旧版本之前,第二个参数“伪类”是必需的,现代浏览器不再是必需参数
//如果不是伪类,则设置为null,
window.getComputedStyle("元素","伪类");
尝试后可以看到window.getCompulatedStyle获取了所有的样式。 如果我们只想得到单一的样式,该怎么办呢? 这个时候我们就要介绍另一种方式——getPropertyValue。
使用方法也很简单:
//句型:
//使用getPropertyValue指定获取的属性
window.getCompulatedStyle("元素", "伪类").getPropertyValue(style);
IE下的currentStyle和getAttribute
说完了常规浏览器,我们再来说说老同学IE,它对应的是getComputedStyle。 在IE中,它有自己独特的currentStyle属性,它对应于getPropertyValue。 IE 使用 getAttribute。
与 getComputedStyle 不同的是,currentStyle 必须采用驼峰式大小写形式才能获取属性名称。 也就是说,如果我需要获取font-size属性,传入的参数应该是fontSize。 因此,要在IE中获取单个属性的值,必须将属性名转换为驼峰式大小写。
//IE下一个句型:
//将CSS命名转换为IE下驼峰式大小写
//字体大小-->字体大小
//可以借助正则进行处理
函数骆驼化(属性){
///-(w)/g 正则表达式中的(w)是捕获,捕获的内容对应上一个函数的字母
//意思是将匹配到的-x结构体的x转换为小写的X(这里的x代表任意字母)
returnattr.replace(/-(w)/g, 函数(全部,字母){
returnletter.toUpperCase();
});
//使用currentStyle.getAttribute获取element元素的style属性style
元素。 当前样式。 getAttribute(骆驼化(样式));
样式和 getCompatedStyle
必须指出的是,我们还可以使用element.style来获取元素的CSS样式声明对象,它和getComputedStyle还是有一些区别的。
首先,element.style是可读可写的,而getComputedStyle是只读的。
其次,element.style只能获取style样式的属性值,而不能获取所有CSS样式值。 这是什么意思? 回顾CSS的基础知识,CSS样式表有三种形式,
内联样式(inlineStyle):写在HTML标签上,内联样式只对该标签有效。
内部样式(internalStyleSheet):写在HTML标签上,内部样式只对其所在网页有效。
外部样式表(ExternalStyleSheet):如果很多网页需要使用同一个样式(Styles),则将样式(Style)写在一个后缀为.CSS的CSS文件中,然后在使用这个样式(Style)的CSS文件中引用在网页中。
而element.style只能获取那些样式表定义的样式,而getComputedStyle可以获取所有样式的值(不同浏览器结果不同,chrome中264,Firefox中238),无论是否定义在样式表中,例如:
varelem=document.getElementById('id');
elem.style.length//2
window.getCompulatedStyle(elem,null).length//264
getCompatedStyle 和 defaultView
window.getCompulatedStyle还有一种写法,就是document.defaultView.getCompulatedStyle。
两者的用法完全一样。 在jQueryv1.10.2中,使用了window.getCompulatedStyle。如下
还有特殊情况,查stackoverflow,有提到在Firefox3.6中,如果不使用document.defaultView.getCompulatedStyle,会出现错误。 不过,尽管 FF3.6 早已随历史而逝去,但您现在可以放心地使用 window.getCompulatedStyle。
用一张图总结一下:
原生JS获取CSS样式的方式
原生JS实现CSS样式的get和set
说了这么多,我们就用原生JS来实现一个小组件,实现CSS的get和set,并且兼容所有浏览器。
完整的组件代码在我的github上,戳我直接看代码。
getStyle(元素,样式)
对于CSS的设置,对于支持window.getCompulatedStyle的浏览器来说非常简单,只需要直接调用即可。
getStyle:函数(元素,样式){
//主流浏览器
if(win.getCompulatedStyle){
返回 win.getCompulatedStyle(elem,null).getPropertyValue(style);
相反,如果是IE浏览器,则存在一些陷阱。
不透明度透明度设置
如果要在早期的IE中设置透明度,有两种方法:
阿尔法(不透明度=0.5)
过滤器:progid:DXImageTransform.Microsoft.gradient(GradientType = 0,startColorstr ='#ccccc',endColorstr ='#ddddd');
所以在IE环境下,我们需要在透明度方面做一些事情。 先写一个IE下获取透明的方法:
//获取IE下的透明度
函数 getIEOpacity(elem){
varfilter=空;
//早期IE中有两种设置透明度的方法:
//1, 阿尔法(不透明度=0)
//2、filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ccccc', endColorstr='#ddddd');
// 正则匹配
filter=elem.style.filter.match(/progid:DXImageTransform.Microsoft.Alpha(.?opacity=(.*).?)/i)||elem.style.filter.match(/alpha(opacity=(. *))/我);
如果(过滤器){
varvalue=parseFloat(过滤器);
if(!isNaN(值)){
// 转换为标准结果
返回值?值/100:0;
//透明度值默认返回1
返回1;
获取浮动样式
float属性是一个比较重要的属性js获取html标签,因为float是ECMAScript的保留字。 (什么是 ECMAScript 保留字?请点击此处)
所以各个浏览器中都会有替代的写法,比如标准浏览器中是cssFloat,IE678中是styleFloat。 经测试,在标准浏览器中也可以直接使用 getPropertyValue("float") 获取 float 的值。 不过IE678不行,所以float也需要HACK。
width|height样式的获取
之后是元素的高度和宽度。 对于没有设置高度和宽度的元素,在IE678下使用getPropertyValue(“width|height”)将得到auto。 标准浏览器会直接返回它的px值,实际上我们希望返回IE下的px值。
这里的HACK方法是使用element.getBoundingClientRect()方法。
element.getBoundingClientRect() – 可以获得元素相对于文档视图左上角的上、左、下、右四个点的值,并且可以通过估计轻松获得准确的元素大小。
获取样式的驼峰命名法表示
上面说了,如果在IE下使用currentStyle来获取属性名,就必须使用驼峰式大小写。
OK,需要HACK的点已经提到了。 所以在IE下,得到这样的写法:
getStyle:函数(元素,样式){
//主流浏览器
if(win.getCompulatedStyle){
...
// 不支持 getCompulatedStyle
}别的{
//获取IE下的透明度
if(样式==“不透明度”){
getIEOpacity(elem);
//IE687下使用styleFloat获取浮点数
}elseif(样式==“浮动”){
returnlem.currentStyle.getAttribute("styleFloat");
//使用getBoundingClientRect获取高度和宽度
}elseif((样式==“宽度”||样式==“高度”)&(elem.currentStyle[样式]==“自动”)){
varclientRect=elem.getBoundingClientRect();
return(style=="width"?clientRect.right-clientRect.left:clientRect.bottom-clientRect.top)+"px";
//其他样式,无需特殊处理
returnlem.currentStyle.getAttribute(camelize(style));
setStyle(元素、样式、值)
说完get,我们来说说setStyle。 与getStyle相比,setStyle要方便得多,因为无论是标准浏览器还是IE,都可以使用element.style.cssText来设置元素的样式。
cssText - 一种设置CSS样式的方法js获取html标签,它是一个破坏原始样式并重建的过程,这将减少浏览器的开销。 而在IE中,如果cssText(如果不为空),最后一个分号会被删除,所以我们需要添加一个“;” 在添加的属性之前。
只是IE下的不透明度需要额外处理。 清晰易懂,直接贴代码:
// 设置样式
setStyle:函数(元素,样式,值){
//如果设置了opacity,需要特殊处理
if(样式==“不透明度”){
//IE7bug:filter过滤器需要hasLayout=true才能执行(否则没有效果)
if(!elem.currentStyle||!elem.currentStyle.hasLayout){
//设置hasLayout=true的方法
elem.style.zoom=1;
//IE678设置透明度称为filter,而不是opacity
样式=“过滤器”;
//!!转换为boolean类型进行区分
if(!!window.XDomainRequest){
value="progid:DXImageTransform.Microsoft.Alpha(style=0,opacity="+value*100+")";
}别的{
值=“alpha(不透明度=“+值*100+”)”
//通用方式
elem.style.cssText+=';'+(样式+":"+值);
至此,原生JS实现的getStyle和setStyle就实现了,完整的代码可以看这里。 可见,一个简单的socket背后,涉及到的东西很多。 其实浏览器兼容性是一个坑,爬坑的过程就是我们安顿自己的最好时机。
像jQuery这样的框架可以帮助我们走得更快,而搞清楚底层实现、掌握原生JS的编写方式无疑可以让我们走得更远。
原创文章文采有限,学识浅薄。 如果文章中有任何不准确的地方,请告诉我。
最后,本文的组件示例的代码发布在我的github()上。
我在github上对jQuery源码的全文注释,有兴趣的可以看一下。 jQueryv1.10.2源码注释()。
【今日陌陌公众号推荐↓】