Javascript createElement相对于innerHTML的优势?

Javascript createElement相对于innerHTML的优势?,javascript,dom,innerhtml,createelement,Javascript,Dom,Innerhtml,Createelement,实际上,与innerHTML相比,使用createElement有哪些优点?我这样问是因为我确信使用innerHTML在性能和代码可读性/可维护性方面更有效,但我的队友已经决定使用createElement作为编码方法。我只是想了解createElement如何更高效 用户在他的文档中非常非常好地添加了许多缺点 。。。另外,您可以通过说$(''+message+'')来创建div,而不必到处乱搞document.createElement('div')和文本节点。好极了只有坚持您没有逃过那个HT

实际上,与innerHTML相比,使用createElement有哪些优点?我这样问是因为我确信使用innerHTML在性能和代码可读性/可维护性方面更有效,但我的队友已经决定使用createElement作为编码方法。我只是想了解createElement如何更高效

用户在他的文档中非常非常好地添加了许多缺点

。。。另外,您可以通过说$(''+message+'')来创建div,而不必到处乱搞document.createElement('div')和文本节点。好极了只有坚持您没有逃过那个HTML,可能只是在客户端创建了一个跨站点脚本安全漏洞。在你花了这么长时间清理你的PHP并在服务器端使用htmlspecialchars之后。真可惜。啊,没有人真正关心正确性或安全性,是吗

jQuery并不是这一切的全部原因。毕竟,innerHTML属性已经存在多年,并且已经证明比DOM更受欢迎。但图书馆肯定鼓励这种编码风格

至于性能:InnerHTML肯定会慢一些,因为它需要解析并在内部转换为DOM元素(可能使用
createElement
方法)

根据@Pointy提供的参数,InnerHTML在所有浏览器中都更快


至于可读性和易用性,在大多数项目中,我会选择
innerHTML
而不是
createElement
。但是正如您所看到的,除了安全性之外,使用
createElement

还有许多优点,使用
createElement
而不是修改
innerHTML
(而不仅仅是扔掉已经存在的东西并替换它),就像Pekka已经提到的那样:

function isArray(a) {
    return Object.prototype.toString.call(a) === "[object Array]";
}

function make(desc) {
    if (!isArray(desc)) {
        return make.call(this, Array.prototype.slice.call(arguments));
    }

    var name = desc[0];
    var attributes = desc[1];

    var el = document.createElement(name);

    var start = 1;
    if (typeof attributes === "object" && attributes !== null && !isArray(attributes)) {
        for (var attr in attributes) {
            el[attr] = attributes[attr];
        }
        start = 2;
    }

    for (var i = start; i < desc.length; i++) {
        if (isArray(desc[i])) {
            el.appendChild(make(desc[i]));
        }
        else {
            el.appendChild(document.createTextNode(desc[i]));
        }
    }

    return el;
}
追加元素时保留对DOM元素的现有引用 当您附加(或以其他方式修改)
innerHTML
时,必须重新解析并重新创建该元素中的所有DOM节点。如果保存了对节点的任何引用,它们基本上是无用的,因为它们不再显示

保留附加到任何DOM元素的事件处理程序 这实际上只是上一个的一个特例(尽管很常见)。设置
innerHTML
不会自动将事件处理程序重新附加到它创建的新元素,因此您必须自己跟踪它们并手动添加它们。在某些情况下,事件委派可以消除此问题

在某些情况下可能更简单/更快 如果您正在进行大量的添加,您肯定不想继续重置
innerHTML
,因为尽管简单更改速度更快,但重复重新解析和创建元素的速度会更慢。解决这个问题的方法是在字符串中构建HTML,并在完成后设置
innerHTML
。根据具体情况,字符串操作可能比仅仅创建元素并附加元素要慢

此外,字符串操作代码可能更复杂(特别是如果您希望它是安全的)

这里有一个我有时使用的函数,它使使用
createElement
更加方便

function isArray(a) {
    return Object.prototype.toString.call(a) === "[object Array]";
}

function make(desc) {
    if (!isArray(desc)) {
        return make.call(this, Array.prototype.slice.call(arguments));
    }

    var name = desc[0];
    var attributes = desc[1];

    var el = document.createElement(name);

    var start = 1;
    if (typeof attributes === "object" && attributes !== null && !isArray(attributes)) {
        for (var attr in attributes) {
            el[attr] = attributes[attr];
        }
        start = 2;
    }

    for (var i = start; i < desc.length; i++) {
        if (isArray(desc[i])) {
            el.appendChild(make(desc[i]));
        }
        else {
            el.appendChild(document.createTextNode(desc[i]));
        }
    }

    return el;
}
您将获得与此HTML相同的内容:

<p>Here is a <a href="http://www.google.com/">link</a>.</p>
这里是一个例子


虽然
innerHTML
可能更快,但我不认为它在可读性或维护方面更好。将所有内容放在一个字符串中可能会更短,但更短的代码并不一定更易于维护

当需要创建动态DOM元素时,字符串连接就不能伸缩,因为加号和引号的开始和结束变得难以跟踪。考虑这些例子:

结果元素是一个具有两个内部跨距的div,其内容是动态的。第一个跨度内的一个类名(warrior)也是动态的

<div>
    <span class="person warrior">John Doe</span>
    <span class="time">30th May, 2010</span>
</div>
仅使用innerHTML并将所有内容混合到一个字符串中,我们可以得到:

someElement.innerHTML = "<div><span class='person " + personClass + "'>" + personName + "</span><span class='time'>" + date + "</span></div>";
​这可以通过在构建对象时分离属性、文本等来改进,以获得对元素构造的更多编程控制。例如,使用MooTools,我们可以将对象属性作为贴图传递。这当然更易于维护,我认为也更具可读性。jQuery1.4使用类似的语法传递用于初始化DOM对象的映射

var div = new Element('div');

var person = new Element('span', {
    'class': 'person ' + personClass,
    'text': personName
});

var when =  new Element('span', {
    'class': 'time',
    'text': date
});

div.adopt([person, when]);
我不认为下面的纯DOM方法比上面的方法更具可读性,但它肯定更易于维护,因为我们不必跟踪开头/结尾引号和许多加号

var div = document.createElement('div');

var person = document.createElement('span');
person.className = 'person ' + personClass;
person.appendChild(document.createTextNode(personName));

var when = document.createElement('span');
​when.className = 'date​​​​​​';
when.appendChild(document.createTextNode(date));

​div.appendChild(person);
div.appendChild(when);
最具可读性的版本很可能是使用某种


var div=$(“#personTemplate”)。创建({
姓名:人名,
类型:personClass,
日期:日期
});

如果希望在代码中保留引用,则应使用createElement。InnerHTML有时会造成难以发现的错误

HTML代码:

<p id="parent">sample <span id='test'>text</span> about anything</p>
1) 你可以改变颜色

2) 您不能再更改颜色或其他任何内容,因为在上面的行中,您向innerHTML添加了一些内容,所有内容都被重新创建,您可以访问不再存在的内容。要更改它,您必须再次获取ElementById

您需要记住,它也会影响任何事件。您需要重新应用事件

InnerHTML非常好,因为它速度更快,大多数时候更容易阅读,但您必须小心使用它。如果你知道你在做什么,你会没事的。

模板文本(模板字符串)是另一个选项

const container = document.getElementById("container");

const item_value = "some Value";

const item = `<div>${item_value}</div>`

container.innerHTML = item;
const container=document.getElementById(“容器”);
const item_value=“某些值”;
常量项=`${item_value}`
container.innerHTML=项目;

Uhh@Pekka你真的确定
innerHTML
会变慢吗?我知道在很长一段时间里,这绝对是错误的。使用
innerHTML<
<div id="personTemplate">
    <span class="person <%= type %>"><%= name %></span>
    <span class="time"><%= date %></span>
</div>

var div = $("#personTemplate").create({
    name: personName,
    type: personClass,
    date: date
});
<p id="parent">sample <span id='test'>text</span> about anything</p>
var test = document.getElementById("test");

test.style.color = "red"; //1 - it works

document.getElementById("parent").innerHTML += "whatever";

test.style.color = "green"; //2 - oooops
const container = document.getElementById("container");

const item_value = "some Value";

const item = `<div>${item_value}</div>`

container.innerHTML = item;