Reputation: 18871
I have a ul with items coming from the loop, and then extra li after that.
<ul>
<todo-item v-for="(todo,index) in todos" v-bind:todo="todo" :key="index" />
<li :key='"new_item"'>
<input placeholder="What needs to be done?" type="text" v-model="new_todo" >
<button v-on:click="add_todo()">Add</button>
</li>
</ul>
This doesn't show the extra line. But if I switch it so extra li is first it does.
<ul>
<li :key='"new_item"'>
<input placeholder="What needs to be done?" type="text" v-model="new_todo" >
<button v-on:click="add_todo()">Add</button>
</li>
<todo-item v-for="(todo,index) in todos" v-bind:todo="todo" :key="index" />
</ul>
So I'm probably doing something wrong with key, but I can't find what exactly.
Upvotes: 2
Views: 1577
Reputation: 644
The problem is that vue components require a closing tag and won't work properly just with self-closing tags.
Try like that:
<ul>
<todo-item v-for="(todo,index) in todos" v-bind:todo="todo" :key="index"></todo-item>
<li :key='"new_item"'>
<input placeholder="What needs to be done?" type="text" v-model="new_todo" >
<button v-on:click="add_todo()">Add</button>
</li>
</ul>
From the official Vue Style Guide:
Components that self-close communicate that they not only have no content, but are meant to have no content. It’s the difference between a blank page in a book and one labeled “This page intentionally left blank.” Your code is also cleaner without the unnecessary closing tag.
Unfortunately, HTML doesn’t allow custom elements to be self-closing - only official “void” elements. That’s why the strategy is only possible when Vue’s template compiler can reach the template before the DOM, then serve the DOM spec-compliant HTML.
Upvotes: 4
Reputation: 41
Do you use SFC or usual HTML files?
Maybe the problem is that HTML parser doesn't allow to use <todo-item>
inside <ul>
. Try to use <li :is="'todo-item'" v-for...>
instead (it's works in your codepen)
<div id="app">
<h1>TODOs</h1>
<ul>
<li :is="'todo-item'" v-for="(todo,index) in todos" v-bind:todo="todo" :key="index"></li>
<li :key='"new_item"'>
<input placeholder="What needs to be done?" type="text" v-model="new_todo" >
<button v-on:click="add_todo()">Add</button>
</li>
</ul>
<p>You have finished {{ done }}/{{ total }}</p>
</div>
https://v2.vuejs.org/v2/guide/components.html#DOM-Template-Parsing-Caveats
Upvotes: 0
Reputation: 7520
You are not allowed to use self-closing tags, so instead of <todo-item />
use <todo-item></todo-item>
https://github.com/vuejs/vue/issues/1036
Not a valid HTML5 components it seems.
Upvotes: 2