解析原生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 相关文章推荐
jQuery实现单行文字间歇向上滚动源代码
Jun 02 Javascript
jquery二级导航内容均分的原理及实现
Aug 13 Javascript
微信分享的标题、缩略图、连接及描述设置方法
Oct 14 Javascript
js实现iframe跨页面调用函数的方法
Dec 13 Javascript
js实现淡入淡出轮播切换功能
Jan 13 Javascript
JS实现分页浏览横向图片(类轮播)实例代码
Nov 06 Javascript
浅析Vue.js 中的条件渲染指令
Nov 19 Javascript
Node 代理访问的实现
Sep 19 Javascript
node.js中对Event Loop事件循环的理解与应用实例分析
Feb 14 Javascript
基于javascript实现碰撞检测
Mar 12 Javascript
vue下载二进制流图片操作
Oct 26 Javascript
js实现移动端轮播图滑动切换
Dec 21 Javascript
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上的memcache和memcached两个pecl库
2010/03/29 PHP
phpmyadmin出现Cannot start session without errors问题解决方法
2014/08/14 PHP
解决php表单重复提交实现方法
2015/09/29 PHP
Js setInterval与setTimeout(定时执行与循环执行)的代码(可以传入参数)
2010/06/11 Javascript
jquery实现文本框鼠标右击无效以及不能输入的代码
2010/11/05 Javascript
用jquery等比例控制图片宽高的具体实现
2014/01/28 Javascript
js数组常见操作及数组与字符串相互转化实例详解
2015/11/10 Javascript
js自定义select下拉框美化特效
2016/05/12 Javascript
DOM 事件的深入浅出(二)
2016/12/05 Javascript
重新理解JavaScript的六种继承方式
2017/03/24 Javascript
jQuery选择器_动力节点Java学院整理
2017/07/05 jQuery
详解关于微信setData回调函数中的坑
2019/02/18 Javascript
使用vue-router在Vue页面之间传递数据的方法
2019/07/15 Javascript
使用vue cli4.x搭建vue项目的过程详解
2020/05/08 Javascript
Vue封装全局过滤器Filters的步骤
2020/09/16 Javascript
[03:03]2014DOTA2国际邀请赛 EG战队专访
2014/07/12 DOTA
利用python打印出菱形、三角形以及矩形的方法实例
2017/08/08 Python
浅谈Pycharm调用同级目录下的py脚本bug
2018/12/03 Python
python3-flask-3将信息写入日志的实操方法
2019/11/12 Python
Python tkinter模版代码实例
2020/02/05 Python
python GUI库图形界面开发之PyQt5布局控件QHBoxLayout详细使用方法与实例
2020/03/06 Python
python rolling regression. 使用 Python 实现滚动回归操作
2020/06/08 Python
联想澳大利亚官网:Lenovo Australia
2018/01/18 全球购物
Lululemon英国官网:加拿大瑜伽服装品牌
2019/01/14 全球购物
Richards网上商店:当代时尚,遍布巴西
2019/11/03 全球购物
linux面试题参考答案(4)
2014/09/21 面试题
转党组织关系介绍信
2014/01/08 职场文书
点菜员岗位职责范本
2014/02/14 职场文书
《童年》教学反思
2014/02/18 职场文书
廉洁使者实施方案
2014/03/29 职场文书
初中升旗仪式演讲稿
2014/05/08 职场文书
安全伴我行演讲稿
2014/09/04 职场文书
商务邀请函
2015/01/30 职场文书
篮球比赛通讯稿
2015/07/18 职场文书
javascript函数式编程基础
2021/09/15 Javascript
HTML5基础学习之文本标签控制
2022/03/25 HTML / CSS