VueJS和vue-router:使用v-link时,视图数据不会更新

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

本文关键字:数据 视图 更新 vue-router 使用 v-link VueJS      更新时间:2023-09-26

我正在尝试使用vue-router的v-link连接VueJS组件。当单击链接时,URL会更新,但除非手动刷新页面,否则视图数据不会更新。

本示例的一些上下文:一个Tour有许多Tour对象,并且Tour对象需要链接到上一个/下一个Tour对象。

下面是表示一个Tour对象的路由:

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

完整的示例:

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>

对于vuejs ^2,您可以观察路由并触发如下更改(在我的情况下,我的用户路由中有username参数):

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

文档中的动态路由匹配

来自文档,(以及gitter通道上@svevil的帮助):

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

还可以使用computed属性,如下所示:

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>