Vue 文档DOM 模板解析警告说:
应当指出的是,这种限制并没有,如果你正在使用字符串模板从下列来源之一适用:
- 字符串模板(例如
template: '...')
注意
is="todo-item"属性。这在 DOM 模板中是必要的 […]
但这不是“字符串模板”吗?
Vue.component('todo-item', {
template: '\
<li>\
{{ title }}\
<button v-on:click="$emit(\'remove\')">Remove</button>\
</li>\
',
props: ['title']
})
Run Code Online (Sandbox Code Playgroud)
您可能对字符串模板的“范围”感到困惑,它使您摆脱了上述限制。
如果限制它可以拥有的子元素类型的 HTML父元素(在本例中为<ul>)位于字符串模板中,那么您就可以了。
但是如果它在真实的 DOM 中,那么浏览器将开始检查限制并提升它不期望的子元素。
Vue 文档中的确切示例可能不再非常相关,因为浏览器现在似乎接受自定义元素作为<ul>(至少在 Chrome 和 Firefox 中)的子元素:
Vue.component('todo-item', {
template: '\
<li>\
{{ title }}\
<button v-on:click="$emit(\'remove\')">Remove</button>\
</li>\
',
props: ['title']
})
new Vue({
el: '#todo-list-example',
data: {
newTodoText: '',
todos: [{
id: 1,
title: 'Do the dishes',
},
{
id: 2,
title: 'Take out the trash',
},
{
id: 3,
title: 'Mow the lawn'
}
],
nextTodoId: 4
},
methods: {
addNewTodo: function() {
this.todos.push({
id: this.nextTodoId++,
title: this.newTodoText
})
this.newTodoText = ''
}
}
})Run Code Online (Sandbox Code Playgroud)
li {
/* Items will be RED if hoisted out of the UL */
background-color: red;
}
ul li {
/* Items will be GREEN if kept inside the UL */
background-color: green;
}Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2"></script>
<div id="todo-list-example">
<form v-on:submit.prevent="addNewTodo">
<label for="new-todo">Add a todo</label>
<input v-model="newTodoText" id="new-todo" placeholder="E.g. Feed the cat">
<button>Add</button>
</form>
<ul>
<!-- Using directly the Component in DOM -->
<todo-item
v-for="(todo, index) in todos"
v-bind:key="todo.id"
v-bind:title="todo.title"
v-on:remove="todos.splice(index, 1)"
></todo-item>
</ul>
</div>Run Code Online (Sandbox Code Playgroud)
但是考虑我们用<ul>a<table>和<li>表行替换的情况<tr><td>:
Vue.component('todo-item', {
template: '\
<tr><td>\
{{ title }}\
<button v-on:click="$emit(\'remove\')">Remove</button>\
</td></tr>\
',
props: ['title']
})
new Vue({
el: '#todo-list-example',
data: {
newTodoText: '',
todos: [{
id: 1,
title: 'Do the dishes',
},
{
id: 2,
title: 'Take out the trash',
},
{
id: 3,
title: 'Mow the lawn'
}
],
nextTodoId: 4
},
methods: {
addNewTodo: function() {
this.todos.push({
id: this.nextTodoId++,
title: this.newTodoText
})
this.newTodoText = ''
}
}
})Run Code Online (Sandbox Code Playgroud)
tr,
td {
/* Cells will be RED if hoisted out of the table */
background-color: red;
}
table tr,
table td {
/* Cells will be GREEN if kept inside the table */
background-color: green;
}Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2"></script>
<div id="todo-list-example">
<form v-on:submit.prevent="addNewTodo">
<label for="new-todo">Add a todo</label>
<input v-model="newTodoText" id="new-todo" placeholder="E.g. Feed the cat">
<button>Add</button>
</form>
<table>
<!-- Using directly the Component in real DOM -->
<todo-item
v-for="(todo, index) in todos"
v-bind:key="todo.id"
v-bind:title="todo.title"
v-on:remove="todos.splice(index, 1)"
></todo-item>
</table>
</div>Run Code Online (Sandbox Code Playgroud)
现在,如果应用程序模板不再留在真实的 DOM 中,但也指定为模板字符串:
Vue.component('todo-item', {
template: '\
<tr><td>\
{{ title }}\
<button v-on:click="$emit(\'remove\')">Remove</button>\
</td></tr>\
',
props: ['title']
})
new Vue({
el: '#todo-list-example',
template: `
<div>
<form v-on:submit.prevent="addNewTodo">
<label for="new-todo">Add a todo</label>
<input v-model="newTodoText" id="new-todo" placeholder="E.g. Feed the cat">
<button>Add</button>
</form>
<table>
<!-- Using directly the Component in template string -->
<todo-item
v-for="(todo, index) in todos"
v-bind:key="todo.id"
v-bind:title="todo.title"
v-on:remove="todos.splice(index, 1)"
></todo-item>
</table>
</div>
`,
data: {
newTodoText: '',
todos: [{
id: 1,
title: 'Do the dishes',
},
{
id: 2,
title: 'Take out the trash',
},
{
id: 3,
title: 'Mow the lawn'
}
],
nextTodoId: 4
},
methods: {
addNewTodo: function() {
this.todos.push({
id: this.nextTodoId++,
title: this.newTodoText
})
this.newTodoText = ''
}
}
})Run Code Online (Sandbox Code Playgroud)
tr,
td {
/* Cells will be RED if hoisted out of the table */
background-color: red;
}
table tr,
table td {
/* Cells will be GREEN if kept inside the table */
background-color: green;
}Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2"></script>
<div id="todo-list-example">
</div>Run Code Online (Sandbox Code Playgroud)
为了完整起见,如果我们将 app 模板保存在真实的 DOM 中,但正确使用is特殊属性来引用我们的组件,如 Vue doc 示例中所做的那样:
Vue.component('todo-item', {
template: '\
<tr><td>\
{{ title }}\
<button v-on:click="$emit(\'remove\')">Remove</button>\
</td></tr>\
',
props: ['title']
})
new Vue({
el: '#todo-list-example',
data: {
newTodoText: '',
todos: [{
id: 1,
title: 'Do the dishes',
},
{
id: 2,
title: 'Take out the trash',
},
{
id: 3,
title: 'Mow the lawn'
}
],
nextTodoId: 4
},
methods: {
addNewTodo: function() {
this.todos.push({
id: this.nextTodoId++,
title: this.newTodoText
})
this.newTodoText = ''
}
}
})Run Code Online (Sandbox Code Playgroud)
tr,
td {
/* Cells will be RED if hoisted out of the table */
background-color: red;
}
table tr,
table td {
/* Cells will be GREEN if kept inside the table */
background-color: green;
}Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2"></script>
<div id="todo-list-example">
<form v-on:submit.prevent="addNewTodo">
<label for="new-todo">Add a todo</label>
<input v-model="newTodoText" id="new-todo" placeholder="E.g. Feed the cat">
<button>Add</button>
</form>
<table>
<!-- Using a TR with "is" in real DOM -->
<tr
is="todo-item"
v-for="(todo, index) in todos"
v-bind:key="todo.id"
v-bind:title="todo.title"
v-on:remove="todos.splice(index, 1)"
></tr>
</table>
</div>Run Code Online (Sandbox Code Playgroud)