问题描述
如官方documentation所述,在新的合成api setup
方法中定义“ data”变量时,我们必须使用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.
}
解决方法
有两件事使它起作用
1)您使用的是方法而不是传递函数
您可以使用标准的Vue API from
或composition API,例如:data:,methods:,etc...
您的示例同时使用了两者。 AFAIK,可以这样做,但是请注意setup()
与setup
传递的方法的行为会有所不同。在一种方法中,您可以访问methods
可变的this
对象
myConst
如果您要使用此示例(如下),则更新 methods: {
operate() {
this.myConst = 'Why this updates?'; // <=== access to mutable variable in `this`
awesomeStore.changeText("yess!");
}
}
无效
myConst
2)您正在更新ref和static
另一个问题是您要更新静态值,然后再更新引用。更改ref将重新触发渲染,此时静态值将发生变化
因此,如果您通过存储删除更新,则应该不会再看到更新发生
setup(){
const myConst = "I'm a const"; // This should be const `myConst = ref('...');`
// ...stuff...
return {
awesomeState,myConst,operate: ()=>{
this.myConst = 'Why this updates?'; // <=== nope
myConst = 'Why this updates?'; // <=== also nope
awesomeStore.changeText("yess!");
}
}
}
这是一个测试我的“理论”的游乐场
methods: {
operate() {
this.myConst = 'Why this updates?';
// awesomeStore.changeText("yess!"); // <== no ref change,no update
}
}
const {
createApp,ref,} = Vue
createApp({
el: '#app',setup() {
let mystatic = 1
const myref = ref(1)
return {
mystatic,myref,updateStatic: () => {
mystatic++
},updateRef: () => {
myref.value++
}
}
},methods: {
updateStaticMethod() {
this.mystatic++
}
}
}).mount('#app')