首页 > 解决方案 > 更改数组长度时,v-for 中的 keep-alive 不起作用

问题描述

我正在尝试从计算值呈现组件。但是,当数组长度从之前的长度发生变化时,<keep-alive>标签就不起作用了。

我希望cOption组件的 created 钩子只触发一次,但它会继续记录其“cOption created!” 每次将flag值切换到时的消息false

我正在使用 Vue 版本 ^2.5.13(使用 Nuxt 版本 1.4.0)

这是我的代码:

new Vue({
  el: '#app',
  data() {
    return {
      flag: false
    }
  },
  computed: {
    options() {
      let opts = []
      if (this.flag) opts.push('aOption')
      else {
        opts.push('bOption', 'cOption')
      }
        
      return opts
    }
  },
  components: {
    defaultOption: {
      template: '<span>defaultOption</span>',
    },
    aOption: {
      template: '<span>aOption {{ flag }}</span>',
      props: {
        flag: {
          type: Boolean,
          default: false
        }
      },
      created: function() {
        console.log("aOption created!")
      },
    },
    bOption: {
      template: '<span>bOption {{ flag }}</span>',
      props: {
        flag: {
          type: Boolean,
          default: false
        }
      },
      created: function() {
        console.log("bOption created!")
      },
    },
    cOption: {
      template: '<span>cOption {{ flag }}</span>',
      props: {
        flag: {
          type: Boolean,
          default: false
        }
      },
      created: function() {
        console.log("cOption created!")
      },
    }
  }
})
<script src="https://unpkg.com/vue@2.5.13"></script>

<div id="app">
  <div>  
    <button @click='flag = !flag'>
        toggle option
    </button>
    <div v-for='option in options'>
        <keep-alive>
          <component :is='option' :flag='flag' :key='option' />
        </keep-alive>
    </div>
  </div>
</div>

这是上面代码的js小提琴

标签: vue.js

解决方案


发生的情况是,当options数组从有两个项目变为只有一个时,第二个<keep-alive>标签和其中的所有内容都被破坏了。因此,当数组变回两个项目时,将<keep-alive>创建组件及其<component>内部。

你想防止<keep-alive>被破坏。一种简单的方法是在值为 时提供一个空字符串作为数组中的第二flagtrue

computed: {
  options() {
    return this.flag ? ['aOption', ''] : ['bOption', 'cOption'];
  }
}

这样,v-for将保持这一秒<keep-alive>左右,而动态<component>不会渲染任何东西。


这是您进行更改的代码:

new Vue({
  el: '#app',
  data() {
    return { flag: false }
  },
  computed: {
     options() {
        return this.flag ? ['aOption', ''] : ['bOption', 'cOption'];
     }
  },
  components: {
    aOption: {
      template: '<span>aOption {{ flag }}</span>',
      props: {
        flag: { type: Boolean, default: false }
      },
      created: function() {
        console.log("aOption created!")
      },
    },
    bOption: {
      template: '<span>bOption {{ flag }}</span>',
      props: {
        flag: { type: Boolean, default: false }
      },
      created: function() {
        console.log("bOption created!")
      },
    },
    cOption: {
      template: '<span>cOption {{ flag }}</span>',
      props: {
        flag: { type: Boolean, default: false }
      },
      created: function() {
        console.log("cOption created!")
      },
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>

<div id="app">
  <div>  
    <button @click='flag = !flag'>toggle option</button>
    <div v-for='option in options'>
      <keep-alive>
        <component  :is='option' :flag='flag' :key='option' />
      </keep-alive>
    </div>
  </div>
</div>


推荐阅读