Reputation: 45
I've read through lots of different threads regarding this topic and unfortunately was not able to find a solution.
I'm currently playing around with a vue / electron app based on typescript. Communication with the electron app is done in an async fashion. Thus, when displaying data on a view or component I often rely on async evaluation of the data I want to display. Upon reading up I came to the conclusion that I need to load data in the mounted() function and set the data on local variables when the data has been fetched.
However, problems arise when I try to utilize computed properties.
I will simplify the case and showcase what does and what doesn't work.
Imagine having the following vue code snippet:
<template>
<div>
{{ text }}
{{ text2 }}
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
@Component
export default class MyComponent extends Vue {
@Prop() public text: string;
private _text2: string;
public get text2() {
return this._text2;
}
public set text2(text2: string) {
this._text2 = text2;
}
mounted() {
// Works:
this.text = "Hello world!";
setTimeout(() => this.text = "Hello world! Overwritten.", 2000);
// Doesn't work
this.text2 = "Hello world!";
setTimeout(() => this.text2 = "Hello world! Overwritten.", 2000);
}
}
</script>
I should also add that the setter text2() gets called twice and the value _text2 is assigned. If I display _text2 instead of text2() in the template then the first assigned value is displayed. The value that is assigned in the timeout shows occasionally. I also played around with Watch() and was unsuccessful.
Maybe some of you know what I'm doing wrong here. I'd appreciate a little push into the right direction.
Upvotes: 1
Views: 1459
Reputation: 407
A solution is to initialise your field that backs your property. This is a little cleaner than having to use the data
field in the component decorator.
private _text2: string = '';
And then access/modify either directly or by using the getter and setter.
Upvotes: 0
Reputation: 45
So it seems that I found the solution. It seems that _text2 is not what is considered to be "reactive". Thus vue can't properly check state changes on this local variable. When I declare _text2 as part of the data function in the component declaration the value is properly recognized.
I don't think this is pretty, because data now has to be accessed using $data.
The access violation error is now gone and the value is updated just as expected.
Maybe someone has a solution that does not involve declaring variables on a separate part than the the class itself.
<template>
<div>
{{ text }}
{{ text2 }}
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
@Component({
data: () => {
return {
_text2: ""
}
}
})
export default class Explorer2 extends Vue {
@Prop() public text: string;
public get text2() {
return this.$data._text2;
}
public set text2(text2: string) {
this.$data._text2 = text2;
}
created() {
// Works:
this.text = "Hello world!";
setTimeout(() => this.text = "Hello world! Overwritten.", 2000);
// Now it works:
this.text2 = "Hello world!";
setTimeout(() => this.text2 = "Hello world! Overwritten.", 2000);
}
}
</script>
Upvotes: 1