【发布时间】:2017-11-01 07:43:51
【问题描述】:
我想在运行时以编程方式向 DOM 元素(例如 HTML 或 SVG 元素)动态添加属性,即基于用户输入。如果属性是标准属性,我将按原样使用名称,但如果不是,即如果它需要转换为自定义属性,那么我想为其添加“data-”前缀。
那么,有没有办法确定一个字符串是否代表一个“标准/正常”的 DOM 属性?
例如,假设我有一个 SVG 矩形,如下所示:
<rect x="10" y="10" width="80" height="40" stroke="black"/>
请注意,尚未(尚未)指定填充颜色。
用户请求添加两个属性:
- 一个名为“fill”且值为“red”的属性,它应该产生
fill="red"(注意没有前缀) - 一个名为“price”的属性,其值为“expensive”,应该产生
data-price="expensive"(注意data-前缀)
如何动态区分这两者? fill 属性不存在于我当前的 DOM 元素中,因此我无法检查该名称的属性是否存在预先存在的值。我也不相信我什至可以检查如果我创建没有前缀的属性是否会引发错误,因为据我所知,至少我当前的浏览器(Chrome v61.0)将允许我添加一个属性price="expensive"(不带 data- 前缀),即使这不是最佳做法。
我想要类似下面的东西:
const elementNodeName = "rect";
const attributeName = "height"; // or, e.g. "price"
const nameIsValid = testAttributeNameValidity(elementNodeName, attributeName);
if (!nameIsValid) attributeName = 'data-' + attributeName;
是否有任何预先存在的testAttributeNameValidity-type 功能?
在寻找 Javascript 解决方案时,我已将其标记为 javascript。
** 更新:其他 SO 答案的解决方案适用于 HTML,但不适用于 SVG **
基于the suggested link in the comments,我尝试使用attributeName in document.createElement(elementNodeName),它应该返回true 作为有效属性名,false 作为无效属性名。当我为 HTML 元素 (<p>) 使用有效的属性名称“id”时,这种方法有效。
相比之下,我还没有在 SVG 中使用这种方法。我尝试将createElement 转换为createElementNS,但这似乎仍然无法解决问题。请参阅下面的测试代码。测试代码中的关键函数是testHtmlAttributeNameValidity 和testSvgAttributeNameValidity。如果您运行代码并检查控制台中的输出,它表明它可以正常用于 HTML,即它会生成 id="someId" data-price="expensive"。但是,对于 SVG,它只会产生不需要的输出:data-fill="yellow" data-price="expensive"。
如果有影响,我正在使用 Chrome v61。
测试代码:
const testHtmlAttributeNameValidity = (elementNodeName, attributeName) => {
return (attributeName in document.createElement(elementNodeName));
};
const testHtmlAttributeName = (attributeName, attributeValue) => {
const elementNodeName = "p";
const nameIsValid = testHtmlAttributeNameValidity(elementNodeName, attributeName);
if (!nameIsValid) attributeName = 'data-' + attributeName;
const element = document.querySelector(elementNodeName);
element.setAttribute(attributeName, attributeValue);
};
testHtmlAttributeName("id", "someId");
testHtmlAttributeName("price", "expensive");
console.log(document.querySelector('div').innerHTML);
const svgNS = "http://www.w3.org/2000/svg";
const testSvgAttributeNameValidity = (elementNodeName, attributeName) => {
return (attributeName in document.createElementNS(svgNS, elementNodeName));
};
const testSvgAttributeName = (attributeName, attributeValue) => {
const elementNodeName = "rect";
const nameIsValid = testSvgAttributeNameValidity(elementNodeName, attributeName);
if (!nameIsValid) attributeName = 'data-' + attributeName;
const element = document.querySelector(elementNodeName);
element.setAttribute(attributeName, attributeValue);
};
testSvgAttributeName("fill", "yellow");
testSvgAttributeName("price", "expensive");
console.log(document.querySelector('svg').innerHTML);
#someId {
color: green;
}
<svg height="55">
<rect x="10" y="10" width="80" height="40" stroke="red"/>
</svg>
<div>
<p>Hello world</p>
</div>
正常工作的代码应该将矩形填充从黑色更改为黄色,这不会发生。
【问题讨论】:
-
这就是制作 XHTML 的原因。然而,每个人都在为 HTML 吐口水。
-
@ShreyanshGandhi,我查看了那个链接,它似乎解决了我的问题。但是,我似乎无法实现它,如对我的问题的更新所示,其中包括不会产生所需结果的测试代码。此外,我尝试将标准的
createElement用于 HTML,但也尝试使用更具体的createElementNS用于 svg...都没有奏效。 -
@ShreyanshGandhi,进一步更新:我在 HTML 中的非工作尝试似乎与我使用属性名称“class”有关,在某些情况下,它应该是“className”。如果我使用属性名称“id”,则链接中的解决方案可以解决问题。但是,即使我使用
createElementNS,我仍然无法让它与 SVG 一起使用。 -
一些 SVG 属性是presentation attributes。其中一些可能具有相应的属性,但大多数可能被视为写为属性的 CSS 样式。它们可以作为 Element.style 界面上的属性找到(如果您发现浏览器不一致和错误的方法)。但是由于这个对象包含 所有 CSS 属性的名称,因此无法通过这种方式判断它们是否也可以用作 SVG 属性。
标签: javascript html svg attributes