在嵌套 getter/setter 中访问顶级 Vue 数据
Accessing top-level Vue data in nested getter/setter
<template>
<div id="app">
{{ foo.bar }}
<button @click="meaning++">click</button> <!--not reactive-->
<button @click="foo.bar++">click2</button>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
@Component
export default class App extends Vue {
private meaning = 42;
private foo = {
that:this,
get bar() {
return this.that.meaning;
},
set bar(value) {
this.that.meaning = value;
},
};
created() {
console.log(this); // VueComponent {}
console.log(this.foo.that); // App {}
console.log(this === this.foo.that); // false
}
}
</script>
我希望 foo.bar
得到 meaning
的支持,这是一个顶级数据字段。我从上面的 hack 开始,将 this
(Vue 选项实例)保存在 that
中,但我也知道在 运行 时,this
成为 VueComponent 实例在组件方法中,因此 this.meaning
不是 this.foo.that.meaning
.
另一个问题是上面的代码片段会在 Chrome 中破坏 vue-devtools
。 vue-devtools
将尝试在 instance._data
上调用 Object.keys()
,即 null
。
让 foo.bar
得到 meaning
支持的正确方法是什么?我可能在那些 getter 和 setter.
中有任意复杂的逻辑
编辑:
由于 this
到 VueComponent 只能在 运行 时解析,我想到了这个有点 hackish 的解决方法:
<template>
<div id="app">
{{ foo.bar }}
<button @click="meaning++">click</button> <!-- reactive now! -->
<button @click="foo.bar++">click2</button>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
@Component
export default class App extends Vue {
private meaning = 42;
private foo = {
that: {meaning:42} as any, // put exactly the same literal initail value here
get bar() {
return this.that.meaning;
},
set bar(value) {
this.that.meaning = value;
},
};
created() {
this.foo.that = this;
console.log(this); // VueComponent
console.log(this.foo.that); // VueComponent
console.log(this === this.foo.that); // true
}
}
</script>
原回答:
对于任何面临同样问题的人,我得出的结论是
it's impossible to refer to outer-level data in inner-level object data in the Vue option instance.
因为VueComponent实例只能在运行的时候抓取,但是你必须在Vue configclass的构造函数中绑定that:this
,这是在实例化之前的 VueComponent。因此 Vue 的响应式系统将没有任何机会更正 that
.
中的引用
所以答案(对我来说)就是不要这样做。依赖项必须始终高于(或处于相同级别)依赖项,并且您不能将 foo
作为 bar
的命名空间。
将 bar
提升到最高级别。
<template>
<div id="app">
{{ foo.bar }}
<button @click="meaning++">click</button> <!--not reactive-->
<button @click="foo.bar++">click2</button>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
@Component
export default class App extends Vue {
private meaning = 42;
private foo = {
that:this,
get bar() {
return this.that.meaning;
},
set bar(value) {
this.that.meaning = value;
},
};
created() {
console.log(this); // VueComponent {}
console.log(this.foo.that); // App {}
console.log(this === this.foo.that); // false
}
}
</script>
我希望 foo.bar
得到 meaning
的支持,这是一个顶级数据字段。我从上面的 hack 开始,将 this
(Vue 选项实例)保存在 that
中,但我也知道在 运行 时,this
成为 VueComponent 实例在组件方法中,因此 this.meaning
不是 this.foo.that.meaning
.
另一个问题是上面的代码片段会在 Chrome 中破坏 vue-devtools
。 vue-devtools
将尝试在 instance._data
上调用 Object.keys()
,即 null
。
让 foo.bar
得到 meaning
支持的正确方法是什么?我可能在那些 getter 和 setter.
编辑:
由于 this
到 VueComponent 只能在 运行 时解析,我想到了这个有点 hackish 的解决方法:
<template>
<div id="app">
{{ foo.bar }}
<button @click="meaning++">click</button> <!-- reactive now! -->
<button @click="foo.bar++">click2</button>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
@Component
export default class App extends Vue {
private meaning = 42;
private foo = {
that: {meaning:42} as any, // put exactly the same literal initail value here
get bar() {
return this.that.meaning;
},
set bar(value) {
this.that.meaning = value;
},
};
created() {
this.foo.that = this;
console.log(this); // VueComponent
console.log(this.foo.that); // VueComponent
console.log(this === this.foo.that); // true
}
}
</script>
原回答:
it's impossible to refer to outer-level data in inner-level object data in the Vue option instance.
因为VueComponent实例只能在运行的时候抓取,但是你必须在Vue configclass的构造函数中绑定that:this
,这是在实例化之前的 VueComponent。因此 Vue 的响应式系统将没有任何机会更正 that
.
所以答案(对我来说)就是不要这样做。依赖项必须始终高于(或处于相同级别)依赖项,并且您不能将 foo
作为 bar
的命名空间。
将 bar
提升到最高级别。