Axel
Axel

Reputation: 5131

Creating/Destroying the Vue Component based on text search

I have the following in App.vue

<template>
    <div id="app">
        <input type="text" v-model="term">
        <hello-world text="Button 1" v-if="term === ''"></hello-world>
        <hello-world v-else text="Button 2"></hello-world>
    </div>
</template>

<script>
import HelloWorld from '@/components/HelloWorld'

export default {
    name: 'app',
    data() {
        return {
            term: ''
        }
    },
    components: {
        HelloWorld
    }
}
</script>

And here's the HelloWorld.vue:

<template>
    <div>
        <button>{{ text }}</button>
    </div>
</template>

<script>
export default {
    props: {
        text: String
    },
    created() {
        console.log('Created')
    },
    destroyed() {
        console.log('Destroyed')
    }
}
</script>

So, when I type something the first component should be destroyed and the second component should be created. However, nothing like that happens. The component neither gets destroyed nor gets created.

It's as if the v-if didn't trigger the created() & destroyed() function. Please help me with this.

Upvotes: 0

Views: 35

Answers (2)

lmarqs
lmarqs

Reputation: 1471

Vue uses virtual dom approach. So, it is comparing the virtual tree and it is not identifying changes on structure (oldNode.type === newNode.type). When it occurs, Vue updates the same component instead of destroying the old node and creating a new one.

Try to force Vue to detect virtual tree changes avoiding use siblings with the same tag name and controlled by v-if directive.

Reference:

https://medium.com/@deathmood/how-to-write-your-own-virtual-dom-ee74acc13060

Vue.component('hello-world', {
  props: {
    text: String
  },
  created() {
    console.log('Created')
  },
  destroyed() {
    console.log('Destroyed')
  },
  template: "<button>{{ text }}</button>"
});

var app = new Vue({
  el: "#app",
  data() {
    return {
      term: ''
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <input type="text" v-model="term">
  <span><hello-world v-if="!term" text="Button 1"></hello-world></span>
  <span><hello-world v-if="term" text="Button 2"></hello-world></span>
</div>

Upvotes: 1

Stamatis Deliyannis
Stamatis Deliyannis

Reputation: 61

I am not sure what you are trying to achieve, but testing your code logs created from both components https://codesandbox.io/s/8l0j43zy89 Since you are actually showing conditionally the same component, I don't think it will get destroyed.

Upvotes: 0

Related Questions