skip to Main Content

I found the statement [].concat(anotherArray) is not completely same to the [...anotherArray].Especially when we use it to convert NodeList.

I want to iterate a NodeList in Vue template, like this:

<div>{{ [...theUl.children].map(li => li.innerText) }}</div>

There is a problem: Vue converts [...theUl.children] to [].concat(theUl.children) and execute it, you can try it yourself, the result is weird and different to [...theUl.children]: you will get a array like [[li, li, li]].
I don’t konw what happened.Who can explain this?
Thank you!

2

Answers


  1. Vue’s reactivity system sometimes interprets the spread operator differently, potentially converting it into a concat operation. This behavior might be due to how Vue compiles templates or handles reactive updates.

    But, the concat() method does not expand non-array iterables by default. When used as [].concat(theUl.children), the method adds the NodeList object as a single element to the new array.

    To avoid this issue, we can explicitly convert the NodeList to an array avoiding any unexpected behavior as below :

    <div>{{ [...Array.from(theUl.children)].map(li => li.innerText) }}</div>

    Login or Signup to reply.
  2. The described behaviour can be caused by Vue template compiler or other transpilers like TypeScript. Vue templates are DSL that can transform JavaScript expressions in an undocumented way. The question didn’ specify Vue version, it could work this way in Vue 2 but not in Vue 3.

    Similarly to other cases, this could be solved by explicitly converting an iterable to an array with Array.from, but the correct way is to not rely on Vue template transforms and move expensive code from a template to a computed, where it will work in more predictable and efficient way:

    listItems() {
      return [...this.theUl.children].map(li => li.innerText)
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search