解析原生JS getComputedStyle


Posted in Javascript onMay 25, 2021

getComputedStyle 与getPropertyValue

getComputedStyle 为何物呢,DOM 中 getComputedStyle 方法可用来获取元素中所有可用的css属性列表,以数组形式返回,并且是只读的。IE678 中则用 currentStyle 代替 。

假设我们页面上存在一个 id 为 id 的元素,那么使用getComputedStyle 获取元素样式就如下图所示:

解析原生JS getComputedStyle

尝试一下之后可以看到,window.getComputedStyle 获取的是所有的样式,如果我们只是要获取单一样式,该怎么做呢。这个时候就要介绍另一个方法 --getPropertyValue。

用法也很简单:

// 语法:
// 使用 getPropertyValue 来指定获取的属性
window.getComputedStyle("元素", "伪类").getPropertyValue(style);

IE 下的 currentStyle与getAttribute

说完常规浏览器,再来谈谈老朋友 IE ,与getComputedStyle 对应,在 IE 中有自己特有的 currentStyle属性,与 getPropertyValue 对应,IE 中使用getAttribute 。

和 getComputedStyle 方法不同的是,currentStyle 要获得属性名的话必须采用驼峰式的写法。也就是如果我需要获取 font-size 属性,那么传入的参数应该是 fontSize。因此在IE 中要获得单个属性的值,就必须将属性名转为驼峰形式。

// IE 下语法:
// IE 下将 CSS 命名转换为驼峰表示法
// font-size --> fontSize
// 利用正则处理一下就可以了
function camelize(attr) {
    // /\-(\w)/g 正则内的 (\w) 是一个捕获,捕获的内容对应后面 function 的 letter
    // 意思是将 匹配到的 -x 结构的 x 转换为大写的 X (x 这里代表任意字母)
    return attr.replace(/\-(\w)/g, function(all, letter) {
        return letter.toUpperCase();
    });
}
// 使用 currentStyle.getAttribute 获取元素 element 的 style 属性样式
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),不管是否定义在样式表中,譬如:

<style>
#id{
    width : 100px;
    float:left;
}
</style>
 
var elem = document.getElementById('id');
 
elem.style.length // 2
window.getComputedStyle(elem, null).length // 264

getComputedStyle 与defaultView

window.getComputedStyle 还有另一种写法,就是 document.defaultView.getComputedStyle 。

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

解析原生JS getComputedStyle

也有特例,查看stackoverflow,上面提及到在Firefox 3.6 ,不使用document.defaultView.getComputedStyle 会出错。不过毕竟 FF3.6 已经随历史远去,现在可以放心的使用window.getComputedStyle。

用一张图总结一下:

解析原生JS getComputedStyle

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

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

getStyle(elem, style)

对于 CSS 的 set ,对于支持window.getComputedStyle 的浏览器而言十分简单,只需要直接调用。

getStyle: function(elem, style) {
    // 主流浏览器
    if (win.getComputedStyle) {
        return win.getComputedStyle(elem, null).getPropertyValue(style);
    }
}

反之,如果是 IE 浏览器,则有一些坑。

opacity 透明度的设定

在早期的 IE 中要设置透明度的话,有两个方法:

1.alpha(opacity=0.5)

2.filter:progid:DXImageTransform.Microsoft.gradient( GradientType= 0 , startColorstr = ‘#ccccc',endColorstr = ‘#ddddd' );

因此在 IE 环境下,我们需要针对透明度做一些处理。先写一个 IE 下获取透明度的方法:

// IE 下获取透明度   
function getIEOpacity(elem) {
    var filter = null;
 
    // 早期的 IE 中要设置透明度有两个方法:
    // 1、alpha(opacity=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=(.*)\)/i);
 
    if (filter) {
        var value = parseFloat(filter);
        if (!isNaN(value)) {
            // 转化为标准结果
            return value ? value / 100 : 0;
        }
    }
    // 透明度的值默认返回 1
    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 下,获取样式的写法:

getStyle: function(elem, style) {
    // 主流浏览器
    if (win.getComputedStyle) {
        ...
    // 不支持 getComputedStyle
    } else {
        // IE 下获取透明度
        if (style == "opacity") {
            getIEOpacity(elem);
        // IE687 下获取浮动使用 styleFloat
        } else if (style == "float") {
            return elem.currentStyle.getAttribute("styleFloat");
                // 取高宽使用 getBoundingClientRect
        } else if ((style == "width" || style == "height") && (elem.currentStyle[style] == "auto")) {
            var clientRect = elem.getBoundingClientRect();
 
            return (style == "width" ? clientRect.right - clientRect.left : clientRect.bottom - clientRect.top) + "px";
        }
        // 其他样式,无需特殊处理
        return elem.currentStyle.getAttribute(camelize(style));
    }
}

setStyle(elem, style, value)

说完 get ,再说说 setStyle ,相较于getStyle ,setStyle 则便捷很多,因为不管是标准浏览器还是 IE ,都可以使用element.style.cssText 对元素进行样式的设置。

cssText -- 一种设置 CSS 样式的方法,但是它是一个销毁原样式并重建的过程,这种销毁和重建,会增加浏览器的开销。而且在 IE 中,如果cssText(假如不为空),最后一个分号会被删掉,所以我们需要在其中添加的属性前加上一个 ”;” 。

只是在 IE 下的 opacity 需要额外的进行处理。明了易懂,直接贴代码:

// 设置样式
setStyle: function(elem, style, value) {
    // 如果是设置 opacity ,需要特殊处理
    if (style == "opacity") {
        //IE7 bug:filter 滤镜要求 hasLayout=true 方可执行(否则没有效果)
        if (!elem.currentStyle || !elem.currentStyle.hasLayout) {
            // 设置 hasLayout=true 的一种方法
            elem.style.zoom = 1;
        }
        // IE678 设置透明度叫 filter ,不是 opacity
        style = "filter";
 
        // !!转换为 boolean 类型进行判断
        if (!!window.XDomainRequest) {
            value = "progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=" + value * 100 + ")";
        } else {
            value = "alpha(opacity=" + value * 100 + ")"
        }
    }
    // 通用方法
    elem.style.cssText += ';' + (style + ":" + value);
}

到这里,原生 JS 实现的 getStyle 与setStyle 就实现了。可以看到,一个简单接口的背后,都是有涉及了很多方面东西。虽然浏览器兼容性是一个坑,但是爬坑的过程却是我们沉淀自己的最好时机。

jQuery 这样的框架可以帮助我们走的更快,但是毫无疑问,去弄清底层实现,掌握原生 JS 的写法,可以让我们走得更远。

以上就是解析原生JS getComputedStyle的详细内容,更多关于原生JS getComputedStyle的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
JavaScript触发器详解
Mar 10 Javascript
JavaScript中的排序算法代码
Feb 22 Javascript
5个最佳的Javascript日期处理类库分享
Apr 15 Javascript
Javascript连接多个数组不用concat来解决
Mar 24 Javascript
JQuery复制DOM节点的方法
Jun 11 Javascript
Javascript函数式编程简单介绍
Oct 11 Javascript
超实用的JavaScript代码段 附使用方法
May 22 Javascript
JavaScript 正则命名分组【推荐】
Jun 07 Javascript
Vue.js中的extend绑定节点并显示的方法
Jun 20 Javascript
解决$store.getters调用不执行的问题
Nov 08 Javascript
JS获取当前时间的年月日时分秒及时间的格式化的方法
Dec 18 Javascript
教你部署vue项目到docker
Apr 05 Vue.js
80行代码写一个Webpack插件并发布到npm
Ajax请求超时与网络异常处理图文详解
May 23 #Javascript
vue-element-admin项目导入和导出的实现
May 21 #Vue.js
vue2实现provide inject传递响应式
May 21 #Vue.js
JS + HTML 罗盘式时钟的实现
JavaScript canvas实现流星特效
May 20 #Javascript
vue使用节流函数的踩坑实例指南
You might like
php array_merge函数使用需要注意的一个问题
2015/03/30 PHP
php隐藏实际地址的文件下载方法
2015/04/18 PHP
PHP 数组基本操作小结(推荐)
2016/06/13 PHP
session 加入redis的实现代码
2016/07/15 PHP
laravel5.5添加echarts实现画图功能的方法
2019/10/09 PHP
JavaScript—window对象使用示例
2013/12/09 Javascript
基于JavaScript实现一定时间后去执行一个函数
2015/12/14 Javascript
最简单的JavaScript图片轮播代码(两种方法)
2015/12/18 Javascript
JavaScript电子时钟倒计时
2016/01/09 Javascript
AngularJS 过滤与排序详解及实例代码
2016/09/14 Javascript
js实现延迟加载的几种方法
2017/04/24 Javascript
JQuery通过后台获取数据遍历到前台的方法
2018/08/13 jQuery
解决JavaScript layui 下拉框不显示的问题
2018/08/14 Javascript
webpack4 入门最简单的例子介绍
2018/09/05 Javascript
jQuery实现飞机大战小游戏
2020/07/05 jQuery
vue 手机物理监听键+退出提示代码
2020/09/09 Javascript
[05:06]2017亚洲邀请赛DAC回顾片
2017/04/19 DOTA
python私有属性和方法实例分析
2015/01/15 Python
Python实现遍历windows所有窗口并输出窗口标题的方法
2015/03/13 Python
Python中使用第三方库xlutils来追加写入Excel文件示例
2015/04/05 Python
python MySQLdb Windows下安装教程及问题解决方法
2015/05/09 Python
Python列表删除的三种方法代码分享
2017/10/31 Python
python+selenium实现163邮箱自动登陆的方法
2017/12/31 Python
python 显示数组全部元素的方法
2018/04/19 Python
对numpy中shape的深入理解
2018/06/15 Python
python实现批量视频分帧、保存视频帧
2019/05/31 Python
如何获取Python简单for循环索引
2019/11/21 Python
Python加速程序运行的方法
2020/07/29 Python
微软加拿大官方网站:Microsoft Canada
2019/04/28 全球购物
考博专家推荐信模板
2013/12/02 职场文书
英文请假条
2014/04/11 职场文书
公司门卫岗位职责范本
2014/07/08 职场文书
机动车交通事故协议书
2015/01/29 职场文书
毕业论文致谢范文
2015/05/14 职场文书
nginx网站服务如何配置防盗链(推荐)
2021/03/31 Servers
Java后台生成图片的完整步骤
2021/08/04 Java/Android