Vue 2.6.12组件Prop在$emit触发及路由切换时未更新的技术求助
Hey there, let's break down exactly what's causing your two main problems and walk through how to fix them step by step:
What's Going Wrong?
1. ComponentOne doesn't update its route path check
Your ComponentOne sets routePath only once in the mounted hook. Since it's rendered directly in General.vue (not inside the <router-view>), it doesn't re-mount when you switch routes. That means the v-if="routePath == 'routetwo'" condition stays stuck on whatever path was active when the component first loaded—so it keeps showing the phone field even when you're on RouteOne.
2. Reactive prop retains old data after route switches
- First, your
reactivePropinGeneral.vueisn't initialized properly (it's justreactivePropwithout a default value). - When you switch to RouteOne, the component's
dataObjectstarts empty, but your watcher only triggers when the data changes. Since there's no initial change, thedata-updatedevent never fires, leavingreactivePropholding the last state from RouteTwo (including the phone field). - You're also passing the same object reference each time you emit, which can lead to unexpected reactivity quirks.
Step-by-Step Fixes
Fix 1: Update ComponentOne's route path dynamically
Add a watcher to ComponentOne so it updates routePath whenever the route changes:
<!-- ComponentOne.vue --> <template> <div> <p>{{ componentProp.id }}</p> <p>{{ componentProp.name }}</p> <p>{{ componentProp.lastname }}</p> <p v-if="routePath == 'routetwo'">{{ componentProp.phone }}</p> </div> </template> <script> export default { props: { componentProp: Object, }, data: () => ({ routePath: '' }), mounted() { this.routePath = this.$route.path.split('/').at(-1); }, // Add watcher for route changes watch: { '$route.path'(newPath) { this.routePath = newPath.split('/').at(-1); } } } </script>
Fix 2: Initialize and reset reactiveProp on route switches
Update General.vue to initialize reactiveProp and reset it whenever the route changes, so it doesn't hold old data:
<!-- General.vue --> <template> <div> <div> <router-view @data-updated="updateFunction"></router-view> </div> <div> <component-one v-bind:component-prop="reactiveProp" /> </div> </div> </template> <script> import ComponentOne from './ComponentOne.vue'; export default { components: { ComponentOne, }, data: () => ({ reactiveProp: {} // Initialize with empty object }), methods: { updateFunction(value) { // Create a new object to avoid reference issues this.reactiveProp = { ...value }; }, }, // Reset prop when route changes watch: { '$route'(to) { if (to.name === 'route-one') { this.reactiveProp = { id: '', name: '', lastname: '' }; } else if (to.name === 'route-two') { this.reactiveProp = { id: '', name: '', lastname: '', phone: '' }; } } } } </script>
Fix 3: Ensure initial data is emitted from child routes
Add a mounted hook to both RouteOne and RouteTwo to emit their initial empty state, so reactiveProp syncs immediately when you switch routes:
RouteOne.vue update:
<script> export default { data: () => ({ dataObject: { id: '', name: '', lastname: '', }, }), mounted() { // Emit initial data when component loads this.$emit('data-updated', { ...this.dataObject }); }, methods: { // some logic methods }, watch: { dataObject: { handler: function() { this.$emit('data-updated', { ...this.dataObject }); }, deep: true, } }, } </script>
RouteTwo.vue update:
<script> export default { data: () => ({ dataObject: { id: '', name: '', lastname: '', phone: '', }, }), mounted() { this.$emit('data-updated', { ...this.dataObject }); }, methods: { // some logic methods }, watch: { dataObject: { handler: function() { this.$emit('data-updated', { ...this.dataObject }); }, deep: true, } }, } </script>
Why This Works
- The route watcher in
ComponentOneensures the phone field only shows when you're actually on RouteTwo. - Initializing and resetting
reactivePropclears out old data when switching routes, so you start fresh each time. - Using
{ ...value }creates a new object each time you emit, breaking shared references and preventing unexpected reactivity bugs. - Emitting initial data on mount makes sure the parent component gets the correct empty state as soon as you switch to a new route.
内容的提问来源于stack exchange,提问作者leandronn

