vue.js DOM 模板解析注意事项

Yip*_*ing 4 html vue.js

Vue 文档DOM 模板解析警告说:

应当指出的是,这种限制并没有,如果你正在使用字符串模板从下列来源之一适用:

  • 字符串模板(例如template: '...'

v-for有一个组件

注意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)

ghy*_*ybs 6

您可能对字符串模板的“范围”感到困惑,它使您摆脱了上述限制。

如果限制它可以拥有的子元素类型的 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)