简体   繁体   中英

VueJS and vue-router: view data does not update when using v-link

I am trying to link between VueJS components using vue-router's v-link . When a link is clicked, the URL is updated, but the view data does not update unless the page is manually refreshed.

Some context for this example: a Tour has many Tour Objects, and Tour Objects need to link to previous/next Tour Objects.

Here's the route that represents a Tour Object:

'/tours/:tourId/objects/:objectId': {
    name: 'tourObject',
    component: tourObjectComponent
}

Full example:

 var App = Vue.extend({}); var tourObjectData = [ { id: "1", name: "Object A" }, { id: "2", name: "Object B" }, { id: "3", name: "Object C" }, { id: "4", name: "Object D" }, { id: "5", name: "Object E" }, ]; var tourComponent = Vue.extend({ template: '#tourComponent', data: function() { return { objects: [], }; }, created: function() { this.objects = tourObjectData; }, }); var tourObjectComponent = Vue.extend({ template: '#tourObjectComponent', data: function() { return { currIndex: null, currObject: {}, prevObject: {}, nextObject: {}, }; }, created: function() { this.currIndex = this.getCurrIndex(); this.currObject = this.getCurrObject(); this.prevObject = this.getPrevObject(); this.nextObject = this.getNextObject(); }, methods: { // Get current object index within tour objects getCurrIndex: function() { for (var i = 0; i < tourObjectData.length; i++) { if (tourObjectData[i].id === this.$route.params.objectId) { return i; } } }, // Get current object getCurrObject: function() { return tourObjectData[this.currIndex]; }, // Get previous object getPrevObject: function() { var prevIndex = this.currIndex > 0 ? this.currIndex - 1 : tourObjectData.length - 1; return tourObjectData[prevIndex]; }, // Get next object getNextObject: function() { var nextIndex = this.currIndex < tourObjectData.length - 1 ? this.currIndex + 1 : 0; return tourObjectData[nextIndex]; }, }, }); var router = new VueRouter(); router.redirect({ // Start on Tour 1 '/': '/tours/1' }); router.map({ // Tour '/tours/:tourId': { name: 'tour', component: tourComponent }, // Object within tour '/tours/:tourId/objects/:objectId': { name: 'tourObject', component: tourObjectComponent } }); router.start(App, '#app');
 <script src="https://cdn.jsdelivr.net/vue/0.12.10/vue.js"></script> <script src="https://rawgit.com/vuejs/vue-router/dev/dist/vue-router.js"></script> <script type="x-template" id="tourComponent"> <h1>Tour</h1> <ul> <li v-repeat="objects"> <a v-link="{name: 'tourObject', params: {tourId: 1, objectId: id}}">{{name}}</a> </li> </ul> </script> <script type="x-template" id="tourObjectComponent"> <a v-link="{name: 'tour', params: {tourId: 1}}">Back to Tour</a> <h1>{{currObject.name}}</h1> <ul> <li><a v-link="{name: 'tourObject', params: {tourId: 1, objectId: prevObject.id}}">Previous Tour Object: {{prevObject.name}}</a></li> <li><a v-link="{name: 'tourObject', params: {tourId: 1, objectId: nextObject.id}}">Next Tour Object: {{nextObject.name}}</a></li> </ul> </script> <div id="app"> <router-view></router-view> </div>

For vuejs ^2, you can watch the route and trigger a change like this (in my case I had username parameter in my user routes):

watch:{
    '$route' (to, from) {
        if (to.params.username !== from.params.username) {
            //update whatever
        }
   }
},

Dynamic Route Matching from documentation

From the doc , (and help from @svevil on the gitter channel):

route: {
    data(transition) {
        transition.next(DataObjectForCurrentRoute);
    }
}

Also, you can use computed properties, like so:

 var App = Vue.extend({}); var tourObjectData = [ { id: "1", name: "Object A" }, { id: "2", name: "Object B" }, { id: "3", name: "Object C" }, { id: "4", name: "Object D" }, { id: "5", name: "Object E" }, ]; var tourComponent = Vue.extend({ template: '#tourComponent', data: function() { return { }; }, computed: { objects: function() { return tourObjectData; } }, }); var tourObjectComponent = Vue.extend({ template: '#tourObjectComponent', data: function() { return { currIndex: null, currObject: {}, prevObject: {}, nextObject: {}, }; }, computed: { currIndex: function() { for (var i = 0; i < tourObjectData.length; i++) { if (tourObjectData[i].id === this.$route.params.objectId) { return i; } }; }, currObject: function() { return tourObjectData[this.currIndex]; }, prevObject: function() { var prevIndex = this.currIndex > 0 ? this.currIndex - 1 : tourObjectData.length - 1; return tourObjectData[prevIndex]; }, nextObject: function() { var nextIndex = this.currIndex < tourObjectData.length - 1 ? this.currIndex + 1 : 0; return tourObjectData[nextIndex]; }, }, }); var router = new VueRouter(); router.redirect({ // Start on Tour 1 '/': '/tours/1' }); router.map({ // Tour '/tours/:tourId': { name: 'tour', component: tourComponent }, // Object within tour '/tours/:tourId/objects/:objectId': { name: 'tourObject', component: tourObjectComponent } }); router.start(App, '#app');
 <script src="https://cdn.jsdelivr.net/vue/0.12.10/vue.js"></script> <script src="https://rawgit.com/vuejs/vue-router/dev/dist/vue-router.js"></script> <script type="x-template" id="tourComponent"> <h1>Tour</h1> <ul> <li v-repeat="objects"> <a v-link="{name: 'tourObject', params: {tourId: 1, objectId: id}}">{{name}}</a> </li> </ul> </script> <script type="x-template" id="tourObjectComponent"> <a v-link="{name: 'tour', params: {tourId: 1}}">Back to Tour</a> <h1>{{currObject.name}}</h1> <ul> <li><a v-link="{name: 'tourObject', params: {tourId: 1, objectId: prevObject.id}}">Previous Tour Object: {{prevObject.name}}</a></li> <li><a v-link="{name: 'tourObject', params: {tourId: 1, objectId: nextObject.id}}">Next Tour Object: {{nextObject.name}}</a></li> </ul> </script> <div id="app"> <router-view></router-view> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM