• 售前

  • 售后

热门帖子
入门百科

剖析原生JS getComputedStyle

[复制链接]
123456823 显示全部楼层 发表于 2021-8-16 11:59:33 |阅读模式 打印 上一主题 下一主题
目录


  • getComputedStyle 与getPropertyValue
  • IE 下的 currentStyle与getAttribute
  • style 与getComputedStyle
  • getComputedStyle 与defaultView
  • 原生JS实现CSS样式的get与set

    • getStyle(elem, style)
    • opacity 透明度的设定
    • float 样式的获取
    • width | height 样式的获取
    • 获取样式的驼峰表现法
    • setStyle(elem, style, value)


getComputedStyle 与getPropertyValue

getComputedStyle 为何物呢,DOM 中 getComputedStyle 方法可用来获取元素中全部可用的css属性列表,以数组情势返回,并且是只读的。IE678 中则用 currentStyle 取代 。
假设我们页面上存在一个 id 为 id 的元素,那么使用getComputedStyle 获取元素样式就如下图所示:

尝试一下之后可以看到,window.getComputedStyle 获取的是全部的样式,如果我们只是要获取单一样式,该怎么做呢。这个时候就要先容另一个方法 --getPropertyValue。
用法也很简单:
  1. // 语法:
  2. // 使用 getPropertyValue 来指定获取的属性
  3. window.getComputedStyle("元素", "伪类").getPropertyValue(style);
复制代码
IE 下的 currentStyle与getAttribute

说完通例浏览器,再来谈谈老朋友 IE ,与getComputedStyle 对应,在 IE 中有本身特有的 currentStyle属性,与 getPropertyValue 对应,IE 中使用getAttribute 。
和 getComputedStyle 方法不同的是,currentStyle 要得到属性名的话必须采用驼峰式的写法。也就是如果我需要获取 font-size 属性,那么传入的参数应该是 fontSize。因此在IE 中要得到单个属性的值,就必须将属性名转为驼峰情势。
  1. // IE 下语法:
  2. // IE 下将 CSS 命名转换为驼峰表示法
  3. // font-size --> fontSize
  4. // 利用正则处理一下就可以了
  5. function camelize(attr) {
  6.     // /\-(\w)/g 正则内的 (\w) 是一个捕获,捕获的内容对应后面 function 的 letter
  7.     // 意思是将 匹配到的 -x 结构的 x 转换为大写的 X (x 这里代表任意字母)
  8.     return attr.replace(/\-(\w)/g, function(all, letter) {
  9.         return letter.toUpperCase();
  10.     });
  11. }
  12. // 使用 currentStyle.getAttribute 获取元素 element 的 style 属性样式
  13. element.currentStyle.getAttribute(camelize(style));
复制代码
style 与getComputedStyle

必须要提出的是,我们使用element.style 也可以获取元素的CSS样式声明对象,但是其与getComputedStyle方法照旧有一些差异的。
首先,element.style 是可读可写的,而getComputedStyle 为只读。
其次,element.style 只可以获取 style 样式上的属性值,而无法得到全部的 CSS 样式值,什么意思呢?回顾一下 CSS 根本,CSS 样式表的表现有三种方式,
1.内嵌样式(inline Style) :是写在 HTML 标签里面的,内嵌样式只对该标签有效。
2.内部样式(internal Style Sheet):是写在 HTML 的 <style> 标签里面的,内部样式只对所在的网页有效。
3.外部样式表(External Style Sheet):如果许多网页需要用到同样的样式(Styles),将样式(Styles)写在一个以 .CSS为后缀的 CSS 文件里,然后在每个需要用到这些样式(Styles)的网页里引用这个 CSS 文件。
而element.style 只能获取被这些样式表定义了的样式,而 getComputedStyle 能获取到全部样式的值(在不同浏览器效果不一样,chrome 中是 264,在 Firefox 中是238),不管是否定义在样式表中,譬如:
  1. <style>
  2. #id{
  3.     width : 100px;
  4.     float:left;
  5. }
  6. </style>
  7. var elem = document.getElementById('id');
  8. elem.style.length // 2
  9. window.getComputedStyle(elem, null).length // 264
复制代码
getComputedStyle 与defaultView

window.getComputedStyle 另有另一种写法,就是 document.defaultView.getComputedStyle 。
两者的用法完全一样,在 jQuery v1.10.2 中,使用的就是window.getComputedStyle 。如下

也有特例,查察stackoverflow,上面提及到在Firefox 3.6 ,不使用document.defaultView.getComputedStyle 会堕落。不过究竟 FF3.6 已经随汗青远去,现在可以放心的使用window.getComputedStyle。
用一张图总结一下:


原生JS实现CSS样式的get与set

说了这么多,接下来将用原生 JS 实现一个小组件,实现 CSS 的 get 与 set,兼容全部浏览器。

getStyle(elem, style)

对于 CSS 的 set ,对于支持window.getComputedStyle 的浏览器而言非常简单,只需要直接调用。
  1. getStyle: function(elem, style) {
  2.     // 主流浏览器
  3.     if (win.getComputedStyle) {
  4.         return win.getComputedStyle(elem, null).getPropertyValue(style);
  5.     }
  6. }
复制代码
反之,如果是 IE 浏览器,则有一些坑。

opacity 透明度的设定

在早期的 IE 中要设置透明度的话,有两个方法:
1.alpha(opacity=0.5)
2.filter:progid:DXImageTransform.Microsoft.gradient( GradientType= 0 , startColorstr = ‘#ccccc',endColorstr = ‘#ddddd' );
因此在 IE 情况下,我们需要针对透明度做一些处置惩罚。先写一个 IE 下获取透明度的方法:
  1. // IE 下获取透明度   
  2. function getIEOpacity(elem) {
  3.     var filter = null;
  4.     // 早期的 IE 中要设置透明度有两个方法:
  5.     // 1、alpha(opacity=0)
  6.     // 2、filter:progid:DXImageTransform.Microsoft.gradient( GradientType= 0 , startColorstr = ‘#ccccc', endColorstr = ‘#ddddd' );
  7.     // 利用正则匹配
  8.     filter = elem.style.filter.match(/progid:DXImageTransform.Microsoft.Alpha\(.?opacity=(.*).?\)/i) || elem.style.filter.match(/alpha\(opacity=(.*)\)/i);
  9.     if (filter) {
  10.         var value = parseFloat(filter);
  11.         if (!isNaN(value)) {
  12.             // 转化为标准结果
  13.             return value ? value / 100 : 0;
  14.         }
  15.     }
  16.     // 透明度的值默认返回 1
  17.     return 1;
复制代码
float 样式的获取

float 属性是比较重要的一个属性,但是由于 float 是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() --可以得到元素四个点相对于文档视图左上角的值 top、left、bottom、right ,通过计算就可以容易地得到精确的元素巨细。

获取样式的驼峰表现法

上文已经提及了,在IE下使用currentStyle 要得到属性名的话必须采用驼峰式的写法。
OK,需要 HACK 的点已经提完了。那么在 IE 下,获取样式的写法:
  1. getStyle: function(elem, style) {
  2.     // 主流浏览器
  3.     if (win.getComputedStyle) {
  4.         ...
  5.     // 不支持 getComputedStyle
  6.     } else {
  7.         // IE 下获取透明度
  8.         if (style == "opacity") {
  9.             getIEOpacity(elem);
  10.         // IE687 下获取浮动使用 styleFloat
  11.         } else if (style == "float") {
  12.             return elem.currentStyle.getAttribute("styleFloat");
  13.                 // 取高宽使用 getBoundingClientRect
  14.         } else if ((style == "width" || style == "height") && (elem.currentStyle[style] == "auto")) {
  15.             var clientRect = elem.getBoundingClientRect();
  16.             return (style == "width" ? clientRect.right - clientRect.left : clientRect.bottom - clientRect.top) + "px";
  17.         }
  18.         // 其他样式,无需特殊处理
  19.         return elem.currentStyle.getAttribute(camelize(style));
  20.     }
  21. }
复制代码
setStyle(elem, style, value)

说完 get ,再说说 setStyle ,相较于getStyle ,setStyle 则便捷许多,因为不管是标准浏览器照旧 IE ,都可以使用element.style.cssText 对元素进行样式的设置。
cssText -- 一种设置 CSS 样式的方法,但是它是一个烧毁原样式并重建的过程,这种烧毁和重建,会增加浏览器的开销。而且在 IE 中,如果cssText(如果不为空),末了一个分号会被删掉,所以我们需要在此中添加的属性前加上一个 ”;” 。
只是在 IE 下的 opacity 需要额外的进行处置惩罚。明确易懂,直接贴代码:
  1. // 设置样式
  2. setStyle: function(elem, style, value) {
  3.     // 如果是设置 opacity ,需要特殊处理
  4.     if (style == "opacity") {
  5.         //IE7 bug:filter 滤镜要求 hasLayout=true 方可执行(否则没有效果)
  6.         if (!elem.currentStyle || !elem.currentStyle.hasLayout) {
  7.             // 设置 hasLayout=true 的一种方法
  8.             elem.style.zoom = 1;
  9.         }
  10.         // IE678 设置透明度叫 filter ,不是 opacity
  11.         style = "filter";
  12.         // !!转换为 boolean 类型进行判断
  13.         if (!!window.XDomainRequest) {
  14.             value = "progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=" + value * 100 + ")";
  15.         } else {
  16.             value = "alpha(opacity=" + value * 100 + ")"
  17.         }
  18.     }
  19.     // 通用方法
  20.     elem.style.cssText += ';' + (style + ":" + value);
  21. }
复制代码
到这里,原生 JS 实现的 getStyle 与setStyle 就实现了。可以看到,一个简单接口的背后,都是有涉及了许多方面东西。固然浏览器兼容性是一个坑,但是爬坑的过程却是我们沉淀本身的最好机遇。
jQuery 如许的框架可以资助我们走的更快,但是毫无疑问,去弄清底层实现,把握原生 JS 的写法,可以让我们走得更远。
以上就是分析原生JS getComputedStyle的具体内容,更多关于原生JS getComputedStyle的资料请关注脚本之家别的相干文章!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作