【问题标题】:What is the behavior of document.createElement when passed as an argument?作为参数传递时 document.createElement 的行为是什么?
【发布时间】:2017-04-17 01:25:46
【问题描述】:

当尝试传递由document.createElement 方法创建的元素时,我们会遇到异常结果:

var Todo = (function () {
  return {
    items: [],
    addItem: function () {
      var task = document
        .querySelector('#top-todo')
        .value
        .trim()
      if (task !== '') {
        this.items.push({ task, complete: false })
        document.querySelector('#top-todo').value = ''
        console.log('Added item: ' + task)
        var newTodo = document.createElement('li')
          .appendChild(document.createElement('p'))
          .appendChild(document.createTextNode(task))
        document.querySelector('#todo-list').appendChild(newTodo)
      }
    }
  }
})()
<div>
  <ul id="todo-list">
    <li>
      <input id="top-todo" placeholder="I need to..." type="text" />
    </li>
  </ul>
  <input onclick="Todo.addItem()" type="button" value="add" />
</div>

我们只看到将 textNode 元素附加到 #todo-list 元素,而不是完全失败或 typeError。这种行为的原因是什么?有没有一种有效的方法可以将该方法用作附加或插入的参数?

【问题讨论】:

  • @charlietfl 我不确定你的意思。
  • 不要将 DOM API 视为 fluent/chainable。它们并非设计为可链接的。如果你想链接使用 jQuery

标签: javascript dom


【解决方案1】:

Node.appendChild

返回值是附加的孩子。

您可以将.parentElement.parentElement(设置为li 的子元素的嵌套元素的数量)链接到最后一个.appendChild() 调用以在newTodo 处获取对document.createElement('li') 的引用

var Todo = (function () {
  return {
    items: [],
    addItem: function () {
      var task = document
        .querySelector('#top-todo')
        .value
        .trim()
      if (task !== '') {
        this.items.push({ task, complete: false })
        document.querySelector('#top-todo').value = ''
        console.log('Added item: ' + task)
        var newTodo = document.createElement('li')
          .appendChild(document.createElement('p'))
          .appendChild(document.createTextNode(task))
          .parentElement.parentElement                    
        document.querySelector('#todo-list').appendChild(newTodo)
      }
    }
  }
})()
<div>
  <ul id="todo-list">
    <li>
      <input id="top-todo" placeholder="I need to..." type="text" />
    </li>
  </ul>
  <input onclick="Todo.addItem()" type="button" value="add" />
</div>

【讨论】:

    【解决方案2】:
    var newTodo = document.createElement('li')
      .appendChild(document.createElement('p'))
      .appendChild(document.createTextNode(task))
    

    .appendChild() 返回附加的元素。当您链接函数时,您将获得链中的最后一个返回值。

    大概是这样的:

    1. 创建lili是当前工作值)
    2. 创建p
    3. p 附加到lip 是当前工作值)
    4. 创建文本节点
    5. 将文本节点附加到p(文本节点是当前工作值)
    6. 将当前工作值分配给newTodo

    然后你继续在文档中插入newTodo,这是一个文本节点。

    这样分解会得到你想要的:

    var newTodo = document.createElement('li');
    newTodo
      .appendChild(document.createElement('p'))
      .appendChild(document.createTextNode(task));
    

    【讨论】:

    • 有趣。我假设appendChild方法在修改后会返回节点树结构的副本:li -> li &gt; p -> li &gt; p { task }
    【解决方案3】:
    document.createElement('li')
    

    返回一个 li 元素

    document.createElement('li')
      .appendChild(document.createElement('p'))
    

    返回一个 p 元素

    document.createElement('li')
      .appendChild(document.createElement('p'))
      .appendChild(document.createTextNode(task))
    

    返回一个文本节点

    所以你实际上是在附加一个文本节点。

    【讨论】:

      猜你喜欢
      • 2021-11-21
      • 1970-01-01
      • 2018-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      相关资源
      最近更新 更多