Javascript 构造DOMTokenList/DOMSettableTokenList实例
DOMTokenList和DOMSettableTokenList接口(,)提供了操作由空格分隔字符串表示的有序字符串标记集的方法。它们最常用的形式是Element.prototype.classList属性,这是一个反映关联元素的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
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');
}