用JS写个兼容IE8浏览器的类选择器

更新日期: 2019-04-02阅读: 2.2k标签: 兼容

基于某些考虑,有时我们项目中会尽量使用原生js,这种情况下连最简单的类选择器可能都要进行兼容性处理。getElementsByClassName是后来引入的,历史不如getElementById和getElementsByTagName。越是新的特性,浏览器的兼容相对就越差。

虽然这3个选择器都并不是百分百兼容所有浏览器,比如getElementById和getElementsByTagName在IE上只支持>=5.5,不过谁还用低于5.5的IE呢?但getElementsByClassName就不同了,它在IE上只支持>=9,所以就存在兼容性的问题。

兼容的方式,就是利用getElementsByTagName来获取所有的标签,然后判断每个标签有没有class,以及class里面的值是不是等于我们要找的。《JavaScript dom编程艺术(第2版)》第42页有一个简单实现,但因为作者只是想说明原理,所以没有完善,用了indexOf去判断我们要的类名在不在标签的类名中,这会导致假如我们要找nam的话会把类名叫name的都找出来。所以网上有很多的实现,大致如下,并且下面的实现还考虑了标签的类名可能有多个类的情况。

<div id="app">
    <p>zero</p>
    <p class="name name-one">one</p>
    <p class="name name-one name-two">two</p>
    <p class="name name-one name-two name-three">three</p>
</div>

<script>
  function getElementsByClassName(node, className){
      // 如果支持原生getElementsByClassName就直接使用并返回结果
      if (node.getElementsByClassName){
          return node.getElementsByClassName(className);
      }
      // 这是最终返回的结果数组
      var results = new Array();
      // 先获取node节点下所有的标签
      var elements = node.getElementsByTagName("*");
      // 循环遍历获得的所有标签
      for (var i = 0; i < elements.length; i++){
          // 获取循环中的标签
          var ele = elements[i];
          // 获取该标签的类名
          var cName = ele.className;
          // 如果类名为空,也就是没有class,那么这个标签肯定不是,所以继续循环下一次标签
          if (cName === ""){
              continue;
          }
          // 如果是多个class,那么就分别获得这几个class
          var cNames = cName.split(" ");
          // 循环遍历标签中的几个class,只要有一个class和我们要的className相等,说明就是匹配的标签
          for (var j = 0; j < cNames.length; j++){
              if (cNames[j] === className){
                  results[results.length] = ele;
                  break;
              }
          }
      }
      return results;
  }
  
  // 使用自定义的类选择器
  var nodes = getElementsByClassName(document.getElementById("app"), "name-three");
  for (var i = 0; i < nodes.length; i++){
      console.log(nodes[i].innerText);
  }
</script>


如果在网络上找类似的实现的话,基本上就是到上面这一步。但上面的实现仍然存在一个缺陷,比如要选择类名既包括name又包括name-three的标签就没法实现。

var nodes = getElementsByClassName(document.getElementById("app"), "name name-three");


但原生的getElementsByClassName是支持多个类名选择的,既然要写一个兼容的自定义类选择器代替原生的,那么这个功能说什么也要上啊。和上面的变化,主要在于我们不仅要处理每个标签可能有多个类名的情况,也要处理我们传入的类名参数可能也是多个类名组成的情况,所以用两层循环可以实现,这里只给出与上面不同的代码部分。

// 标签:如果是多个class,那么就分别获得这几个class
var cNames = cName.split(" ");
// 我们要找的类名:如果是多个class,那么就分别获得这几个class
var classNames = className.split(" ");

// 设置一个标记,默认为true,如果在循环判断中发现有条件不满足,设置为false
var flag = true;
// 先循环我们要找的每一个类名
for (var j = 0; j < classNames.length && flag; j++){
    // 看看我们的这个类名在不在这个标签的所有类名中
    for (var k = 0; k < cNames.length; k++){
        if (classNames[j] === cNames[k]){
            break;
        }else if(classNames[j] !== cName[k] && k === cNames.length - 1){
            // 循环到标签最后一个类名了,还不相等,就说明不匹配
            flag = false;
            break;
        }
    }
}

// 如果符合条件,就加入结果集然后返回
if (flag){
    results[results.length] = ele;
}


至此,就可以用我们自定义的类选择器查找多个类都匹配的标签了。如果还要完善的话,至少还需要判断用户传入的类名参数是否为空这种情况。

如果还要加强功能的话,可以考虑实现一个多级选择器的功能,比如jquery中如下的语句,甚至还可以优化循环遍历的写法等。

// 选择id为app下的所有class名有name的标签
$("#app .name")


实现一个功能简单,做成一个产品很难。不过话说回来,如果要自定义太复杂的功能,我们当初在选择原生js时就会更加慎重了。


链接: https://fly63.com/article/detial/2660

CSS/CSS3常用的样式兼容,样式总结

这篇文章主要介绍了css中常用但是又难记的样式作为总结,方便大家学习和使用。包括了‘单行缩略号‘、’css圆角兼容’、‘元素阴影’,‘border取消宽度影响’,‘css3的背景渐变’,‘css的透明’等等

CSS3 nth-child的使用,详解css中nth的作用,以及nth-child的兼容写法

:nth-child是css3的一个比较常用的选择器。它用于匹配属于其父元素中的子元素,不论元素的类型。 它的参数可以是数字、关键词或公式。

CSS 3中-webkit-, -moz-, -o-, -ms-这些私有前缀的含义和兼容

css3作为页面样式的表现语言,增加了很多新的属性,但是部分css3属性在一些浏览器上还处于试验阶段,所以为了有效的显示css3的样式,对应不同的浏览器内核需要不同的前缀声明。

css定义变量_css原生变量的使用和兼容 附带还有更高性能,文件更高压缩率的好处

在开发中,css样式有一些属性往往需要重复使用,为了避免代码冗余,降低维护成本。我们需要使用CSS预编译工具【Sass/Less/Stylus】,随着这些工具的流行,CSS变量也开始规范制定,目前很多浏览器都已经支持了

caniuse.com_判断浏览器对css3、html5的兼容性测试工具

caniuse.com 是一个工具性的网站,帮助人们了解各个浏览器以及它们的不同版本对 HTML5、CSS3 等高级特性的支持情况。直接在上面的输入框中输入想要搜索的属性。然后结果就直接出来了。

web浏览器在线兼容性测试工具_检测html网页在不同浏览器上的兼容问题

对于web前端开发者而言,为了确保html代码在不同浏览器上能正常工作,是一件很麻烦的事情,幸运的是,有很多优秀的工具可以帮助测试浏览器的兼容性,下面就为大家推荐一下比较流行的web浏览器在线兼容性测试工具。

原生js兼容写法_在ie标准下的兼容性写法

经常使用原生js,就要考虑到一些浏览器上的兼容,尤其是IE,下面就整理关于js的一些兼容性写法

解决IE不兼容document.getElementByClassName()的实现方法

在使用原生js时候,需要通过class样式名来获取dom对象,发现在IE8以下是不支持document.getElementByClassName()这种方法的。那么我们如何来实现获取classname的兼容写法呢?

es6之解构赋值

es6的语法已经出了很长的时间了,在使用上也可以通过babel这类的编译工具转译为浏览器可以识别的es5的语法,这篇文章主要会介绍解构赋值基本用法以及在实际使用场景中相比es5语法的优势

document.head.appendChild(element) 在 IE8 及以下报错

问题:在开发中会遇到动态添加 script 标签的情况。但是在 IE8 以下会报如下错误:SCRIPT5007: Unable to get value of the property appendChild: object is null or undefined,解决办法如下

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!