Как указано в официальной документации, при определении нашей переменной данных в новой композиции api setup
, мы должны использовать ref
или reactive
, чтобы Vue мог отслеживать любые изменения в этой конкретной переменной.
Я экспериментирую с реактивностью и обнаружил странное поведение. Возьмите этот компонент этот компонент как ссылку:
App.vue
<template>
<div id="app">
<p>{{ awesomeState.txt }}</p>
<p>{{ myConst }}</p>
<button @click="operate">Test it</button>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import awesomeStore from "@/AwesomeStore";
export default defineComponent({
setup() {
const awesomeState = awesomeStore.getState();
const myConst = "I'm a const"; // This should be const `myConst = ref('...');`
return {
awesomeState,
myConst
};
},
name: "App",
methods: {
operate() {
this.myConst = 'Why this updates?';
awesomeStore.changeText("yess!");
}
}
});
</script>
AwesomeStore.ts
import { reactive, readonly, watch } from "vue";
export abstract class Store<T extends Record<string, any>> {
protected state: T;
constructor() {
const data = this.data();
this.state = reactive(data) as T;
watch(() => this.state, (value) => {
console.log(value); debugger;
}, {deep: true});
}
protected abstract data(): T;
public getState(): T {
return readonly(this.state) as T;
}
}
interface Test extends Object {
txt: string;
}
class AwesomeClass extends Store<Test> {
protected data(): Test {
return {
txt: "init"
};
}
public changeText(msg: string) {
this.state.txt = msg;
}
}
export default new AwesomeClass();
Когда я нажимаю кнопку, свойство myConst
обновляется. Кроме того, я не должен определять метод за пределами setup()
, я не понимаю, почему это происходит.
Кто-нибудь может получить подсказку?
Заранее спасибо,
ОБНОВЛЕНИЕ
Я забыл упомянуть, что открытое поведение имеет место только в том случае, если я пытаюсь изменить константу вместе с методом awesomeStore.changeText
:
operate() {
this.myConst = 'Why this updates?';
//awesomeStore.changeText("yess!"); <-- If commented, myConst do not update.
}