美文网首页
自己实现dom的classList功能

自己实现dom的classList功能

作者: 陈成熟 | 来源:发表于2019-07-24 15:08 被阅读0次

classList属性返回元素的类名,它是一个DOMTokenList对象。相比较className来说,它的操作更加简洁,类似于对数组的操作。

通过控制台,我们可以看到,DOM元素的classList是一个DomTokenList对象,结构类似于数组:

image

不过classList在IE10以下,并不能支持classList。因此,来看看如何自己实现一个classList。

首先,我们知道 div,span等html标签,有一个共同的父类,就是HTMLElement

image

我们要在它上面,创建一个新的prototype。

首先我们想到了直接定义:

HTMLElement.prototype.newClassList = [];
myDiv.newClassList.push('classTest');
console.log(myDiv.newClassList);
console.log(mySpan.newClassList);

但是这样会有个问题,就是通过prototype定义属性,属性的值是共享的。因此当我们给myDiv的newClassList.push的时候,也改变了mySpan,这显然不符合我们的要求。


改变myDiv的属性,也改变了mySpan

因此,我们可以采用Object.defineProperty这个方法,来实现,给我们的HTMLElement定义属性。

Object.defineProperty(HTMLElement.prototype,"newCLassList",{
      get: function(){
          // 因为this是唯一的,所以是一对一,每一次在内存里开辟一个
          if(!this.__dtl__){
              // __dtl__现在是一个数组对象,如果变成类数组对象?
              this.__dtl__ = this.className.split(" ");  //把字符串通过" "分割成字符数组
              
              // 改变它的__proto__,变成NeDOMTokenList的实例,就变成了类数组
              this.__dtl__.__proto__ = new NeDOMTokenList(this);
          }
          return this.__dtl__;
      }
});

为什么要把这个属性变成类数组呢?是因为我们既要让它拥有数组的特性,也要可以有自己的方法,就是add(),remove(),toggle(),contains()...
接下来我们,写一个构造器。

function NeDOMTokenList(dom){

}

然后我们再在构造器里添加方法,因为prototype定义的方法是共享的,所以在这里可以使用。

NeDOMTokenList.prototype = {
      constructor:NeDOMTokenList,
      contains:function(class){
        return [].includes.call(this,class);    
      },
      add:function(class){
        [].push.call(this,class);  
        this.value = [].join.call(this," ");
        return this;
      },
      remove:function(class){
        for(var i = 0;i < this.length;i++){
          if(class === this[i]){
            [].splice.call(this,i,1);
            this.value = [].join.call(this," ");
          }
        }
        return this;
      },
      toggle:function(class){
        this.contains(class)?this.remove(class):this.add(class);
        return this;
      }
}

我们给构造器里创建了几个操作类数组的方法,因为这个实例是类数组对象,所以我们可以直接通过[].join.call(this," ");[].push.call(this,class);调用数组的方法。
那么我们现在可以直接使用 myDiv.neCLassList.add("classB") 等方法了,但是这样仅仅是改变了这个属性的value,如何通知并改变DOM的classname呢?
很简单,我们在构造器里监听一下。

function NeDOMTokenList(dom){
      //dom.className
      // 如何修改dom的className呢,监听只要实例的value改变,就修改dom的className。
      Object.defineProperty(this,"value",{
        set:function(newValue){
          dom.className = newValue;
        }
      })
    }

至此,我们就完成了classList的构造,要修改dom的class,直接使用myDiv.newClassList.add('classB')。。。就可以实现。

相关文章

  • 自己实现dom的classList功能

    classList属性返回元素的类名,它是一个DOMTokenList对象。相比较className来说,它的操作...

  • DOM —— classList

    element.classList有哪些方法?如何判断一个元素的 class 列表中是包含某个 class?如何添...

  • js高级程序设计笔记18

    DOM 1.getElementByClassName() 2.classList

  • js+css3底部下划线导航菜单代码

    使用知识点: Html DOM classList属性 定义和用法 classList 属性返回元素的雷鸣,作为D...

  • dom.classList

    今天逛贴吧无意中发现classList的新属性,classList是className的升级版,问:classLi...

  • js杂记

    事件 window.onscroll() 鼠标滑动事件 DOM操作 selector.classList.add(...

  • HTML DOM classList 属性

    定义和用法: classList 属性返回元素的类名,作为 DOMTokenList 对象。该属性用于在元素中添加...

  • 实现一个 jQuery 的 API

    想要实现一个以下功能用原生js的DOM API来实现一个类jQuery API的功能 1、首先获取DOM元素 判断...

  • JS代码题14

    实现类似getElementsByClassName 的功能 自己实现一个函数,查找某个DOM节点下面的包含某个c...

  • JavaScript Events事件汇总

    事件参数、事件捕获冒泡 事件委托 事件默认行为 DOM 1 、DOM 2、DOM 3模型 实现遮罩功能(点击穿透、...

网友评论

      本文标题:自己实现dom的classList功能

      本文链接:https://www.haomeiwen.com/subject/jfvalctx.html