Javascript 构造DOMTokenList/DOMSettableTokenList实例

Javascript 构造DOMTokenList/DOMSettableTokenList实例,javascript,dom,Javascript,Dom,DOMTokenList和DOMSettableTokenList接口(,)提供了操作由空格分隔字符串表示的有序字符串标记集的方法。它们最常用的形式是Element.prototype.classList属性,这是一个反映关联元素的class属性的DOMTokenList var div=document.createElement('div'); div.setAttribute('class','hello world goodnight moon'); var list=div.clas

DOMTokenList和DOMSettableTokenList接口(,)提供了操作由空格分隔字符串表示的有序字符串标记集的方法。它们最常用的形式是Element.prototype.classList属性,这是一个反映关联元素的
class
属性的DOMTokenList

var div=document.createElement('div');
div.setAttribute('class','hello world goodnight moon');
var list=div.classList;
console.assert(list.length==4);
断言(列表[0]='hello');
console.assert(list.item(1)==“world”);
assert(list.contains('moon')==true);
assert(list.contains('mars')==false);
列表。删除(‘世界’、‘地球’、‘泥土’、‘沙子’);
添加('hello','mars');
list.toggle(“晚安”);

assert(div.getAttribute('class')=='hello moon mars')不能直接创建DOMTokenList或DOMSettableTokenList。相反,您应该使用class属性来存储和检索数据,并可能将DOM元素的ids属性映射到classList属性

    var element = document.querySelector('so-users');
    element.ids = element.classList;
您可以根据文档使用relList,但是classList更受支持,唯一的缺点是,如果您的一个id与类名匹配,那么您可能会遇到问题,因此设置一个内联样式以隐藏元素以防万一

对于自定义组件,兼容性应该是一个问题(IE>=10、Firefox 3.6、Chrome 8、Opera 11.5和Safari 5.1中都有类列表,请参阅),因此,如果兼容性符合您的要求,请使用下面发布的另一个解决方案

如果不能使用CLASE或classList和/或必须使用ids属性,则应根据规范实现自定义函数,并将以下属性作为函数

  • 项目(
  • 包含()
  • 添加()
  • 删除()
  • 切换()
这是此类功能的示例实现

var TokenList = function (ids) {
    'use strict';
    var idsArray = [],
        self = this,
        parse = function (id, functionName, cb) {
            var search = id.toString();
            if (search.split(' ').length > 1) {
                throw new Error("Failed to execute '" + functionName + "' on 'TokenList': The token provided ('" + search + "') contains HTML space characters, which are not valid in tokens.');");
            } else {
                cb(search);
            }
        };

    function triggerAttributeChange() {
        if (self.tokenChanged && typeof self.tokenChanged === 'function') {
            self.tokenChanged(idsArray.toString());
        }
    }

    if (ids && typeof ids === 'string') {
        idsArray = ids.split(' ');
    }
    self.item = function (index) {
        return idsArray[index];
    };

    self.contains = function (id) {
        parse(id, 'contains', function (search) {
            return idsArray.indexOf(search) !== -1;
        });
    };

    self.add = function (id) {
        parse(id, 'add', function (search) {
            if (idsArray.indexOf(search) === -1) {
                idsArray.push(search);
            }
            triggerAttributeChange();
        });
    };

    self.remove = function (id) {
        parse(id, 'remove', function (search) {
            idsArray = idsArray.filter(function (item) {
                return item !== id;
            });
            triggerAttributeChange();
        });
    };

    self.toggle = function (id) {
        parse(id, 'toggle', function (search) {
            if (!self.contains(search)) {
                self.add(search);
            } else {
                self.remove(search);
            }
        });
    };

    self.tokenChanged = null;

    self.toString = function () {
        var tokens = '',
            i;
        if (idsArray.length > 0) {
            for (i = 0; i < idsArray.length; i = i + 1) {
                tokens = tokens + idsArray[i] + ' ';
            }
            tokens = tokens.slice(0, tokens.length - 1);
        }
        return tokens;
    };
};
依次单击按钮,使用初始化方法将ids属性设置为“3456 9876”

,然后重试

var XFooProto=Object.create(HTMLElement.prototype);
// 1. 给x-foo一个foo()方法。
XFooProto.contains=函数(id){
var data=JSON.parse(this.dataset.ids);
返回数据.some(函数(\u id){
返回id==\u id
})
};
XFooProto.add=函数(id){
var data=JSON.parse(this.dataset.ids);
如果(!this.contains(id)){
数据推送(id);
};
返回数据
};
XFooProto.remove=函数(id){
var data=JSON.parse(this.dataset.ids);
如果(本文件包含(id)){
for(数据中的变量id){
如果(数据[_id]==id){
数据拼接(_id,1)
}
};
};
返回数据
};
XFooProto.ids=函数(){
返回this.dataset.ids
};
// 2. 定义只读“栏”属性。
//defineProperty(XFooProto,“ids”,{value:this});
// 3. 注册x-foo的定义。
var XFoo=document.registereElement('x-foo',{prototype:XFooProto});
// 4. 实例化一个x-foo。
var xfoo=document.createElement('x-foo');
xfoo.dataset.ids='[“23354”,“115866”];
// 5. 将其添加到页面中。
document.body.appendChild(xfoo);
console.log(xfoo.add(“123”);//`["23354", "115866", "123"]`
console.log(xfoo.remove(“123”);//`["23354", "115866"]`
console.log(xfoo.contains(“123”);//`假的`
console.log(xfoo.contains(“23354”);//`真的`
console.log(xfoo.ids());//`[“23354”,“115866”]`,类型:`String`
var pre=document.getElementsByTagName(“pre”)[0]
pre.innerText=JSON.stringify(JSON.parse(xfoo.dataset.ids)),null,4

我在Chrome和Firefox的源代码中进行了快速搜索,没有发现任何方法可以在每次需要新实例时不创建新的绑定元素。也许有一些聪明的黑客可能我错过了,或者有一天会出现。我认为这是不可能的,请看(并关注相关问题)。您可能必须使用,这也允许您对方法调用作出反应。@JeremyBanks?@JeremyBanks使用
ids
属性而不是
class
属性的原因是什么?@JeremyBanks有趣的问题。在HTML5Rocks文章中尝试过一些例子,特别是,您所期望的方法可能是可行的,只需做一些调整。另一种方法是利用
元素。数据集
-定义
添加
删除
包含与
元素相关的
函数。数据集
-而不是试图将
DOMTokenList
合并到实现中。主要功能是否需要并附加到
ids
属性
add
contains
remove
var attachTokenList = function (element, prop, initialValues) {
    'use strict';
    var initValues = initialValues || element.getAttribute(prop),
        MutationObserver = window.MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
        observer,
        config,
        cancelMutation = false;

    function createTokenList(values) {
        var tList = new TokenList(values);
        tList.tokenChanged = function () {
            element.setAttribute(prop, element[prop].toString());
            cancelMutation = true;
        };
        element[prop] = tList;
    }

    createTokenList(initValues);

    observer = new MutationObserver(function (mutation) {
        var i,
            mutationrec,
            newAttr;
        if (mutation.length > 0 && !cancelMutation) {
            for (i = 0; i < mutation.length; i = i + 1) {
                mutationrec = mutation[i];
                if (mutationrec.attributeName === prop && element[prop]) {
                    newAttr = element.getAttribute(prop);
                    createTokenList(newAttr);
                }
            }
        }
        cancelMutation = false;
    });

    config = {
        attributes: true
    };
    observer.observe(element, config);
};
<so-users ids="1234 5678"></so-users>
<button onclick="clickButton1()">Add 7890</button>
<button onclick="clickButton2()">Set to 3456</button>
<button onclick="clickButton3()">Add 9876</button>
var elem = document.querySelector('so-users');
attachTokenList(elem, 'ids')

function clickButton1 () {
    elem.ids.add('7890');
}

function clickButton2 () {
    elem.setAttribute('ids', '3456');
}

function clickButton3 () {
    elem.ids.add('9876');
}