如何获取元素的最终background-color


Posted in Javascript onFebruary 06, 2017

一、题目

  用JS代码求出页面上一个元素的最终的background-color,不考虑IE浏览器,不考虑元素float情况。

二、题目解析

  1.考察底层JavaScript基础

  前端开发,日常最常接触的就是页面样式的编写。而摆脱jQuery等工具库,用原生js获取样式,是每个前端程序猿进阶阶段必须掌握的技能。

  2.考察面试者的思维缜密程度和开发经验

  如果认为单单求元素计算后的样式,就有点too young了。页面的样式的复杂,永远是最虐心的。就算前端有多牛逼,一听到兼容IE6,论谁都会心塞?。所以还要考虑特殊的情况:display,opacity,visibility的取值。

三、理论基础

  1. 内联样式

  内联样式可以通过元素的style属性获取,如果style属性有background-color值,则可以直接获取出来 (暂不考虑!important) 。

  2. 外联的层叠样式

  DOM2样式规范在document.defaultView中包含了一个getComputedStyle()方法。该方法返回一个只读的CSSStyleDeclaration对象,其中包含特定元素的所有计算样式。

四、解题

4.1 将所有工具方法封装在WDS(wall dom script)命名空间中

(function(WDS, undefined){
 // 封装代码...
})(window.WDS || (window.WDS = {}));

代码封装在命名空间里,不会造成无意间的代码污染。

4.2 工具方法camelize

// 字符串转换为驼峰写法
function camelize(str) {
 return str.replace(/-(\w)/g, function (strMatch, p1){
  return p1.toUpperCase();
 });
}

该方法是为了方便后续getStyle()方法的编写,而独立出来的。

作用是将连字符类的css属性值,转换成驼峰写法。

例如:将background-color转换为backgroundColor

4.3 获取特定元素的计算样式

// 获取元素计算后的样式
function getStyle(elem, property){
 if(!elem || !property){
  return false;
 }
 var value = elem.style[camelize(property)], // 先获取是否有内联样式
  css; // 获取的所有计算样式
 // 无内联样式,则获取层叠样式表计算后的样式
 if(!value){
  if(document.defaultView && document.defaultView.getComputedStyle){
   css = document.defaultView.getComputedStyle(elem, null);
   value = css ? css.getPropertyValue(property) : null;
  }
 }
 return value;
}

做到这一步,第一个考察点基本就满足了。也能获知面试者是否具备足够扎实的js基础。

另外,像安全保护性的判断if(!elem || !property)和功能嗅探if(document.defaultView && document.defaultView.getComputedStyle),都能很好地体现开发者的代码逻辑和开发经验。

4.4 排除特殊情况

// 检测获取的背景色是否有效
function checkBgValue(elem){
 var value = getStyle(elem, 'background-color'),
  hasColor = value ? true : false; // 是否有颜色
 // 排除特殊情况
 if(value == "transparent" || value == "rgba(0, 0, 0, 0)"){
  // 未设置background-color,或者设置为跟随父节点
  hasColor = false;
 }else if(getStyle(elem, 'opacity') == "0"){
  // dom节点透明度为全透明
  hasColor = false;
 }else if(getStyle(elem, 'visibility') == "hidden"){
  // dom节点不可见
  hasColor = false;
 }else if(getStyle(elem, 'display') == "none"){
  // dom节点不可见
  hasColor = false;
 }
 return hasColor;
}

4.5 获取div在页面最终显示的颜色

// 获取div最终显示的颜色
function getRealBg(elem){
 if(checkBgValue(elem)){
  return getStyle(elem, 'background-color');
 }else if(elem != document.documentElement){
  return getRealBg(elem.parentNode);
 }
 return '';
}

  获取样式值采用递归方式处理。

  如果能顺利获取到元素样式,且不触发4.4 排除特殊情况中的一种,则直接返回结果。

  触发了特殊情况,则需要查找父节点以及更上层的节点的样式,来获取肉眼能看到,显示在页面上的background-color值。

  在向上回溯的过程中,如果已经回溯到html根节点,则可以停止回溯。所以加了判断else if(elem != document.documentElement)

五、遗漏的大boss

5.1 大boss !important

  如果乱用 !important,对大型项目的维护和开发,绝对是一场噩梦。因为优先级规则的计算,!important永远处在食物链的最顶层。

  当前题目不考虑这种情况,也是我的偷懒?。确实很棘手,就不写这个逻辑分支的代码了。这里提醒一下~

5.2 大boss 父节点及根节点设置了不可见css属性

  只要设置该css语句:html {display:none;},页面所有元素立刻消失不见。而任意特定元素的上级节点,只要设置了 opacity,display,visibility,判断逻辑瞬间变得复杂起来。所以,这个浑水我也不趟 O(∩_∩)O哈哈~

六、改进的点

  其实特殊情况排除的判断,我偷懒没做到最好——rgb颜色值和特定颜色值(比如red)没有进行统一的转换,只是加了生硬的判断if(value == "transparent" || value == "rgba(0, 0, 0, 0)")。

有兴趣的可以搜索下颜色值转换的js方法,这里我就不写了。

七、源码和demo

源码地址:https://github.com/wall-wxk/blogDemo/blob/master/2017/02/05/getStyle.html

demo:https://wall-wxk.github.io/blogDemo/2017/02/05/getStyle.html

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
写了10年的Javascript也未必全了解的连续赋值运算
Mar 25 Javascript
js document.write()使用介绍
Feb 21 Javascript
浅谈jQuery异步对象(XMLHttpRequest)
Nov 17 Javascript
JS实现带关闭功能的阿里妈妈网站顶部滑出banner工具条代码
Sep 17 Javascript
详解angularjs中的隔离作用域理解以及绑定策略
May 31 Javascript
简单说说angular.json文件的使用
Oct 29 Javascript
Vue中对iframe实现keep alive无刷新的方法
Jul 23 Javascript
webgl实现物体描边效果的方法介绍
Nov 27 Javascript
JS实现压缩上传图片base64长度功能
Dec 03 Javascript
JavaScript中this的学习笔记及用法整理
Feb 17 Javascript
利用原生JS实现欢乐水果机小游戏
Apr 23 Javascript
js实现九宫格布局效果
May 28 Javascript
a标签置灰不可点击的实现方法
Feb 06 #Javascript
最常见和最有用的字符串相关的方法详解
Feb 06 #Javascript
jquery uploadify隐藏上传进度的实现方法
Feb 06 #Javascript
Javascript中的prototype与继承
Feb 06 #Javascript
canvas实现粒子时钟效果
Feb 06 #Javascript
javascript笔记之匿名函数和闭包
Feb 06 #Javascript
如何用JS/HTML将时间戳转换为“xx天前”的形式
Feb 06 #Javascript
You might like
PHP中将数组转成XML格式的实现代码
2011/08/08 PHP
PHP实现mysqli批量执行多条语句的方法示例
2017/07/22 PHP
XRegExp 0.2: Now With Named Capture
2007/11/30 Javascript
javascript获取浏览器类型和版本的方法(js获取浏览器版本)
2014/03/13 Javascript
JavaScript解八皇后问题的方法总结
2016/06/12 Javascript
javascript时间差插件分享
2016/07/18 Javascript
JavaScript中Array的实用操作技巧分享
2016/09/11 Javascript
详细分析JS函数去抖和节流
2017/12/05 Javascript
JavaScript使用indexOf()实现数组去重的方法分析
2018/09/04 Javascript
浅谈vue权限管理实现及流程
2020/04/23 Javascript
[01:20:05]DOTA2-DPC中国联赛 正赛 Ehome vs VG BO3 第二场 2月5日
2021/03/11 DOTA
python使用itchat实现手机控制电脑
2018/02/22 Python
python采集微信公众号文章
2018/12/20 Python
Python语言检测模块langid和langdetect的使用实例
2019/02/19 Python
pandas 选取行和列数据的方法详解
2019/08/08 Python
django项目登录中使用图片验证码的实现方法
2019/08/15 Python
Python实现图像去噪方式(中值去噪和均值去噪)
2019/12/18 Python
浅谈tensorflow中Dataset图片的批量读取及维度的操作详解
2020/01/20 Python
Python发送邮件封装实现过程详解
2020/05/09 Python
Python是什么 Python的用处
2020/05/26 Python
解决python 执行sql语句时所传参数含有单引号的问题
2020/06/06 Python
python输出结果刷新及进度条的实现操作
2020/07/13 Python
CSS3 Media Queries(响应式布局可以让你定制不同的分辨率和设备)
2013/06/06 HTML / CSS
canvas拼图功能实现代码示例
2018/11/21 HTML / CSS
小程序canvas中文字设置居中锚点
2019/04/16 HTML / CSS
科颜氏美国官网:Kiehl’s美国
2017/01/31 全球购物
short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
2014/09/26 面试题
大一自我鉴定范文
2013/10/04 职场文书
关于安全的演讲稿
2014/05/09 职场文书
2014离婚协议书范文两篇
2014/09/15 职场文书
开展党的群众路线教育实践活动个人对照检查材料
2014/11/05 职场文书
开学典礼观后感
2015/06/15 职场文书
辞职离别感言
2015/08/04 职场文书
《工作是最好的修行》读后感3篇
2019/12/13 职场文书
mongodb数据库迁移变更的解决方案
2021/09/04 MongoDB
如何解决php-fpm启动不了问题
2021/11/17 PHP