【问题标题】:VueJS Adding data from query parametersVueJS 从查询参数中添加数据
【发布时间】:2016-12-21 05:35:08
【问题描述】:

我正在开发一个小型纯客户端 VueJS 应用程序,它使用VueRouter 在数据输入应用程序时更新 URL,因此用户可以使用 URL 刷新页面并将数据重新加载到应用程序中刷新页面。数据存储在查询参数中,例如: .../app.html#/?time=300&time=300&distance=300&distance=300&unit=m&unit=m

router 会根据需要解析数据,但是当我将数据添加到空的performance 数组时,我的标记中的:class 属性会引发一个

TypeError: 无法读取未定义的属性“长度”

其中undefinedperformances 数组。通过从应用程序的标记中删除:class,我已将此问题缩小到v-for 性能循环内的:class 属性,并成功呈现了该站点。我猜performances数据数组还没有传递给:class

我在VueRouter 文档中没有看到任何提及这种类型的路由。应该如何将数据从 URL 查询参数传递到应用程序?以下是我的相关代码(为简洁起见进行了精简):

// js file
var router = new VueRouter({}); // empty because no routes, just query parameters, so no need for list

var app = new Vue({
    el: '#app',
    data: function() {
        return {
            performances: [],
            units: units,
            newPerformance: {
                distance: {
                    value: '',
                    units: units.distance.options[0]
                },
                time: {
                    formatted: '',
                    value: ''
                },
            },
            editingPerformance: null,
        }
    },
    router: router,
    watch: {
        performances: {
            handler: function() {
                this.drawChart();
                this.updateURL();
            },
            deep: true
        }
    },
    updateURL: function() {
        var times = this.performances.map(function(v) {
                return v.time.value
            }),
            distances = this.performances.map(function(v) {
                return v.distance.value
            }),
            units = this.performances.map(function(v) {
                return v.distance.units.value
            });
        router.push({
            query: {
                time: times,
                distance: distances,
                dunit: units
            }
        });
    }
    ....
});

HTML 文件

...
<div v-for="(performance, index) in performances" :class="{'card-list': performances.length > 1 }">
...
</div>
...

我已阅读 Reactivity in Depth 文档并尝试了以下解决方案: Vue.nextTick(function() { this.performances.push(performance); })

Vue.set(app, 'performances',performanceArray);

这会导致相同的错误。我可以根据要求提供更多代码。

编辑:添加堆栈跟踪:

[Vue warn]: Error when rendering root instance: warn @ vue.js:513
Vue._render @ vue.js:2934
(anonymous function) @ vue.js:2335
get @ vue.js:1643run @ vue.js:1712
flushSchedulerQueue @ vue.js:1530
(anonymous function) @ vue.js:465
nextTickHandler @ vue.js:414

紧随其后的是:

vue.js:427 TypeError: Cannot read property 'length' of undefined(…)
logError @ vue.js:427

【问题讨论】:

  • 我建议制作一个组件并通过您的应用包含该组件,而不是尝试在您的应用中制作这些方法

标签: javascript pushstate vue-router vue.js vuejs2


【解决方案1】:

您似乎将其设置为代码中某处的数组以外的其他内容。您将其实例化为一个数组,而 .length 仅适用于数组和字符串,因此如果将其设置为对象、json 或其他任何内容,它将出错。 Vue.nextTick 有一个回调,除非你将它设置为与 Vue.nextTick 函数相同范围内的变量,否则它不会将“this”带入其中。像

var self = this;

//inside nextTick

self.performances.push(performance);

但我想你不应该使用 nextTick,因为 nextTick 会在 DOM 重新渲染后更新。 push() 函数将触发 dom 重新渲染,这将使您的页面响应。如果您等待 nextTick,那么它可能永远不会更新,直到您更改其他内容。

<div v-if="performances.length" v-for="(performance, index) in performances" 
:class="performances.length > 1 ? 'card-list' : ''">
...
</div>

v-if 属性将确保在内容存在之前它不会呈现。

这应该可以解决您的问题

您还可以执行 {{ performance }} 来找出对象中的确切内容,并且 Google chrome 有一个 vue-debugger 扩展。它向您展示了所有数据属性的实时模型。我会推荐使用它。

【讨论】:

  • 原来我遇到了不同的问题。在另一行(当然,我忽略了)上,我有:class="{'hide': performance.label.length === 0, ... } 行,其中标签未在我的路由器中定义。一旦我把它拿出来,我的代码就按预期工作了。我会将您的答案标记为正确,因为如果我将 performances 数组设置为数组以外的其他值,那将是我的问题的正确答案。我刚刚验证了这一点,以确保这会解决它。感谢您的帮助。
  • 当然,谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多