【问题标题】:Prevent same component tags in v-if, v-else, v-else-if from sharing a Vue instance防止 v-if、v-else、v-else-if 中的相同组件标签共享一个 Vue 实例
【发布时间】:2018-04-04 09:25:47
【问题描述】:

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

似乎这些组件被实例化为同一个实例。我在组件的created 挂钩中调用console.log(),并在页面加载时收到一条消息到控制台。然而,当我点击显示另一个数据表时,相应的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>

【问题讨论】:

    标签: vuejs2 vue-component


    【解决方案1】:

    发生这种情况是因为默认情况下,Vue 会尽可能通过重用组件来节省时间。您的&lt;managed-list&gt; 组件可能在v-ifv-else-if 对的&lt;section&gt; 标记中,因此Vue 只是保留该组件而不是销毁并立即重新渲染它。

    如果你想强制 Vue 将两个 &lt;managed-list&gt; 标签中的每一个与它自己的组件相关联,你应该为每个组件标签添加一个唯一的 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.


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

    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';
        }
      }
    })
    <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>

    【讨论】:

    • 正是我需要的...感谢您的详细解释!
    猜你喜欢
    • 2021-11-25
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2021-01-19
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    相关资源
    最近更新 更多