简体   繁体   English

VueJS 从查询参数中添加数据

[英]VueJS Adding data from query parameters

I am working on a small purely client-side VueJS application that uses VueRouter to update the URL when data is entered into the application, so users can use the URL to refresh the page and reload their data into the app when refreshing the page.我正在开发一个小型纯客户端 VueJS 应用程序,该应用程序使用VueRouter在将数据输入应用程序时更新 URL,因此用户可以使用 URL 刷新页面并在刷新页面时将数据重新加载到应用程序中。 The data is stored in query parameters, ex.:数据存储在查询参数中,例如:

.../app.html#/?time=300&time=300&distance=300&distance=300&unit=m&unit=m

The data is parsed as needed by the router , but when I add the data to my empty performance array, the :class attribute in my markup raises a router根据需要解析数据,但是当我将数据添加到我的空performance数组时,我的标记中的:class属性会引发

TypeError: Cannot read property 'length' of undefined TypeError:无法读取未定义的属性“长度”

Where undefined is the performances array.其中undefinedperformances数组。 I have narrowed this issue down to the :class attribute inside of the v-for performance loop by removing the :class from the app's markup and successfully rendered the site.我通过从应用程序的标记中删除:class并成功呈现了站点,将这个问题缩小到v-for性能循环内的:class属性。 I am guessing that the performances data array has not been passed to the :class .我猜performances数据数组尚未传递给:class

I did not see any mention of this type of routing in the VueRouter documentation.我在VueRouter文档中没有看到任何提及这种类型的路由。 How should data be passed from the URL query parameters into the application?应该如何将数据从 URL 查询参数传递到应用程序? Here is my relevant code (condensed for the sake of brevity):这是我的相关代码(为简洁起见进行了精简):

// 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 file HTML 文件

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

I have read the Reactivity in Depth documentation and tried such solutions as:我已阅读Reactivity in Depth文档并尝试了以下解决方案:

    Vue.nextTick(function() {
        this.performances.push(performance);
    })

and

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

which result in the same error.导致相同的错误。 I can provide more code upon request.我可以根据要求提供更多代码。

Edit: Adding stack traces:编辑:添加堆栈跟踪:

[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

followed immediately by:紧随其后的是:

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

It seems like you might be setting it to something other than an array somewhere in your code.似乎您可能将其设置为代码中某处的数组以外的其他内容。 You instantiated it as an array, and .length only works on arrays and strings so if you set it to an object, json, or anything else it will error out.您将其实例化为一个数组,而 .length 仅适用于数组和字符串,因此如果将其设置为对象、json 或其他任何内容,它将出错。 Vue.nextTick has a callback that won't carry "this" over into it unless you set it to a variable in the same scope as your Vue.nextTick function. Vue.nextTick 有一个回调,除非你将它设置为与 Vue.nextTick 函数相同范围内的变量,否则它不会携带“this”。 something like就像是

var self = this;

//inside nextTick

self.performances.push(performance);

but i would imagine that you shouldn't have to use nextTick because nextTick updates after the DOM has been re-rendered.但我想你不应该使用 nextTick 因为在重新渲染 DOM 后 nextTick 会更新。 the push() function will trigger a dom re-render, which will make your page responsive. push() 函数将触发 dom 重新渲染,这将使您的页面响应。 If you wait for nextTick then it may never update until you change something else.如果您等待 nextTick 那么它可能永远不会更新,直到您更改其他内容。

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

The v-if attribute will make sure that it doesn't render until the content is there. v-if 属性将确保在内容存在之前它不会呈现。

That should fix your problem那应该可以解决您的问题

You can also do {{ performance }} to find out what is exactly in the object, and Google chrome has a vue-debugger extension.您还可以执行 {{ performance }} 来找出对象中的确切内容,并且 Google chrome 有一个 vue-debugger 扩展。 It shows you a live model of all of your data properties.它向您展示了所有数据属性的实时模型。 I would recommend using it.我会推荐使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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