Reputation: 29987
I have a component which is mounted as part of the DOM rendering. The skeleton of the application is
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>title</title>
</head>
<body>
<div id="app">
<my-component></my-component>
<button>press this button to reload the component</button>
</div>
</body>
</html>
<my-component>
is functional (it displays a few form inputs) and $emit
data to the parent.
Is there a way to re-mount it? The goal is to have a component content and setup as if it was just rendered for the first time (including a reset of the data()
elements which hold its state).
There are some solutions to that but they all assume a rewrite of data()
, which I would like to avoid.
My understanding is that a component is actuall HTML/CSS/JS code injected in the dom in the right place during the rendering so I fear that the concept of "re-mounting" it does not exist - I just wanted to make sure before going the data()-rewrite way.
Upvotes: 43
Views: 54836
Reputation: 283
In your template you'll add the v-if
directive:
<template>
<my-component v-if="renderComponent" />
</template>
In your script you'll add in this method that uses nextTick
:
<script>
export default {
data() {
return {
renderComponent: true,
};
},
methods: {
forceRerender() {
// Remove my-component from the DOM
this.renderComponent = false;
this.$nextTick(() => {
// Add the component back in
this.renderComponent = true;
});
}
}
};
</script>
This is what's going on here:
- Initially
renderComponent
is set totrue
, somy-component
is rendered- When we call
forceRerender
we immediately setrenderComponent
tofalse
- We stop rendering
my-component
because thev-if
directive now evaluates tofalse
- On the next tick
renderComponent
is set back totrue
- Now the
v-if
directive evaluates totrue
, so we start renderingmy-component
again
Upvotes: 15
Reputation: 35684
When the key changes, vue regards it as a new component, so it will unmount the "old" component, and mount a "new" component.
See example, the created()
hook will only run once, so if you see the value change, you're seeing a brand new object.
example:
Vue.component('my-component', {
template: `<div>{{ rand }}</div>`,
data() {
return {
remount: true
}
},
created() {
this.remount = !this.remount; // true▶false▶true▶false...
}
});
new Vue({
el: '#app',
data: {
componentKey:0
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.8/vue.min.js"></script>
<div id="app">
<my-component :key="componentKey"></my-component>
<button @click="componentKey=!componentKey">press this button to reload the component</button>
</div>
Upvotes: 94