Vue:在同一组件的两个实例之间切换不会更新视图

Posted

技术标签:

【中文标题】Vue:在同一组件的两个实例之间切换不会更新视图【英文标题】:Vue: toggling between two instances of the same component doesn't update the view 【发布时间】:2020-12-29 16:07:22 【问题描述】:

我在 Vue 驱动的 UI 中有一个设置,用户可以在几个选项之间切换某个 div 的内容,其中两个选项恰好是同一个子组件的实例(传入不同的属性) .

第一次显示任何给定的内容页面时,或者在两个不相关的内容页面之间切换时,一切正常。但是,当在两个使用相同子组件的页面之间切换时,div 内容不会得到更新。

在代码中它看起来(大大简化)如下:

父组件

<template>
  <div>
    <!-- toggle buttons -->
    <div class="page-button" @click="page=1">About</div>
    <div class="page-button" @click="page=2">Dog List</div>
    <div class="page-button" @click="page=3">Cat List</div>

    <!-- page content -->
    <div v-if="page===1">some plaintext here...</div>
    <div v-if="page===2">
      <childComponent :state="state" listName="dogs" />
    </div>
    <div v-if="page===3">
      <childComponent :state="state" listName="cats" />
    </div>
    <!-- rest of file omitted -->

childComponent.vue

<template>
  <div>
    <template v-for="(item, index) in items">
      <div> index :  item.label </div>
      <!-- etc.. -->
    </template>
  </div>
</template>

<script>
module.exports = 
    props: ['state', 'listName'],
    data: function () 
        return 
            items: this.state.lists[this.listName],
        
    ,

</script>

在上面,state 是所有组件都可以访问的全局状态对象,state.lists.dogsstate.lists.cats 是常规数组。

当 UI 初始化并将 page 设置为 2 或 3 时,一切正常 - 狗列表显示在第 2 页,猫列表显示在第 3 页。同样,当我单击第 2 页,然后单击第 1 页时,然后第3页,一切都很好。但是当在 2/3 页之间来回切换时,vue 不会重新渲染子组件。

我认为可以通过更改底层数据结构或以不同方式绑定子组件来解决此问题。但是有没有一种直接的方法可以让 Vue 按预期重新渲染组件?

【问题讨论】:

【参考方案1】:

我猜你看到的是 Vue 试图通过重用现有的组件实例来优化渲染。在 childComponent 上添加 key 属性并使用不同的值...

<!-- page content -->
    <div v-if="page===1">some plaintext here...</div>
    <div v-if="page===2">
      <childComponent :state="state" listName="dogs" key="dogs" />
    </div>
    <div v-if="page===3">
      <childComponent :state="state" listName="cats" key="cats" />
    </div>
<!-- rest of file omitted -->

其他解决方案(以及更好的恕我直言)是让您的组件对道具更改“反应” - 而不是使用道具来初始化 data() (这是“一次性”的事情 - data() 仅在以下情况下执行一次组件已创建),使用computed

module.exports = 
  props: ['state', 'listName'],
  computed: 
    items() 
      return this.state.lists[this.listName]
    
  ,

【讨论】:

啊哈!不知道 key 应用在循环之外等。干杯!【参考方案2】:

如果您只想提前渲染,可以使用 v-show。它的成本更高,但它应该可以正常工作。

<template>
  <div>
    <!-- toggle buttons -->
    <div class="page-button" @click="page=1">About</div>
    <div class="page-button" @click="page=2">Dog List</div>
    <div class="page-button" @click="page=3">Cat List</div>

    <!-- page content -->
    <div v-show="page===1">some plaintext here...</div>
    <div v-show="page===2">
      <childComponent :state="state" listName="dogs" />
    </div>
    <div v-show="page===3">
      <childComponent :state="state" listName="cats" />
    </div>
    <!-- rest of file omitted -->

【讨论】:

以上是关于Vue:在同一组件的两个实例之间切换不会更新视图的主要内容,如果未能解决你的问题,请参考以下文章

layoutAnimation 在两个视图之间切换时会在 Android 上导致额外的蓝色背景

当多个路由地址对应同一组件时,切换路由组件不刷新的问题

vue-route 切换 视图不更新

另一个实例视图中的实例视图

react多个路由共用同一个组件模块,切换路由跳转页面不刷新问题

浅析Vue.nextTick()原理