在v-if,v-else,v-else-if中共享Vue实例时,防止相同的组件标记

时间:2017-10-23 18:19:41

标签: vuejs2 vue-component

我有一个VueJS组件<managed-list>,我在同一个模板中使用两次来显示两组不同的数据。每个容器都显示在自己的<section>容器中,该容器在导航选项卡上使用v-if切换。

似乎这些组件被实例化为同一个实例。我在组件的console.log()挂钩中调用created,在页面加载时,我收到一条消息给控制台。但是,当我选中以显示其他数据表时,相应的v-if呈现的模板,但created挂钩不会再次触发。

我的理解是,在模板中使用v-if语句时,组件会被正确创建和销毁。但在我的情况下似乎并没有发生这种情况。我做错了吗?

<template>
  <div>
    <ul class="nav nav-tabs">
      <li class="nav-item">
        <router-link class="nav-link" :class="{active: $route.params.tab=='reports'}" to="reports">Reports</router-link>
      </li>
      <li class="nav-item">
        <router-link class="nav-link" :class="{active: $route.params.tab=='snippets'}" to="snippets">Snippets</router-link>
      </li>
    </ul>

    <section v-if="$route.params.tab == 'reports'">
      <h2>Reports</h2>

      <managed-list 
        :imports-disabled="true" 
        prop-delete-endpoint="ReportTemplate/delete" 
        prop-resource-url="ReportTemplate"
        :prop-fetch-url="'ReportTemplate/filter?filters='+reportFilter"
        prop-edit-action="/reports/templates/edit/{?}">
      </managed-list>
    </section>

    <section v-else-if="$route.params.tab == 'snippets'">
      <h2>Snippets</h2>

      <managed-list 
        :imports-disabled="true" 
        prop-delete-endpoint="ReportTemplate/delete" 
        prop-resource-url="ReportTemplate"
        :prop-fetch-url="'ReportTemplate/filter?filters='+snippetFilter"
        prop-edit-action="/reports/templates/edit/{?}">
      </managed-list>
    </section>
  </div>

</template>

<script>
import ManagedList from "./ManagedList"
import bus from '../bus.js'

export default {
  name: 'ReportTemplates',
  components: {
    ManagedList
  },
  data() {
    return {
      snippetFilter : JSON.stringify([
        ["is_snippet","=", 1]
      ]),
      reportFilter : JSON.stringify([
        ["is_snippet","=", 0]
      ])
    }
  },
  created() {
    console.log(this.snippetFilter, this.reportFilter)
  }
}
</script>

1 个答案:

答案 0 :(得分:3)

这种情况正在发生,因为默认情况下,Vue尝试通过重用组件来节省时间。您的<managed-list>组件同时包含<section>v-if对的v-else-if个标签,因此Vue只是保留该组件而不是销毁并立即重新呈现它。

如果要强制Vue将两个<managed-list>标记中的每一个与其自己的组件相关联,则应为每个组件标记添加唯一的key属性:

<section v-if="$route.params.tab == 'reports'">
  <h2>Reports</h2>
  <managed-list key="reports" ... />
</section>

<section v-else-if="$route.params.tab == 'snippets'">
  <h2>Snippets</h2>
  <managed-list key="snippets" ... />
</section>

Here's the Vue documentation on that.

这是一个简单的说明性示例:

&#13;
&#13;
Vue.component('child', {
  template: '<p>I am child</p>',
  created() {
    console.log('created')
  }
})

new Vue({
  el: '#app',
  data() {
    return { foo: 'a' }
  },
  methods: {
    toggle() {
      this.foo = (this.foo === 'a') ? 'b' : 'a';
    }
  }
})
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js"></script>
<div id="app">
  <button @click="toggle">
    Toggle Children
  </button>

  <template v-if="foo === 'a'">
    <div> 
      A <child key="a"></child>    
    </div>
  </template>
  <template v-else-if="foo === 'b'">
    <div> 
      B <child key="b"></child>    
    </div>
  </template>
</div>
&#13;
&#13;
&#13;