TypeScript VueJS:使用具有计算属性的观察器
Posted
技术标签:
【中文标题】TypeScript VueJS:使用具有计算属性的观察器【英文标题】:TypeScript VueJS: Using watcher with computed property 【发布时间】:2021-03-07 08:12:13 【问题描述】:我正在构建一个自定义组件,它允许我使用任意 <div>
s 作为单选按钮。目前我的代码如下所示:
<template>
<div
class="radio-div"
:class="selected ? 'selected' : ''"
@click="handleClick"
>
<slot></slot>
</div>
</template>
<style lang="scss" scoped>
.radio-div
display: inline-block;
border-radius: 5px;
border: 1px solid #000;
padding: 5px;
margin: 5px;
.radio-div.selected
box-shadow: 0 0 10px rgba(255, 255, 0, 0.5);
border: 2px solid #000;
</style>
<script lang="ts">
import Vue, Component, Prop, Watch from "vue-property-decorator";
@Component
export default class RadioDiv extends Vue
@Prop()
val!: string;
@Prop(
required: true
)
value!: string;
selected = false;
mounted()
this.selected = this.value === this.val;
@Watch("value")
onChange()
this.selected = this.value === this.val;
handleClick(e: MouseEvent)
this.$emit("input", this.val);
</script>
为了利用它,我可以将它放在这样的模板中:
<template>
<div class="q-pa-md">
<q-card>
<q-card-section class="bg-secondary">
<div class="text-h6">Political Affiliation</div>
</q-card-section>
<q-separator />
<q-card-section>
<radio-div v-model="politicalParty" val="Republican">
<div class="text-h6">Republican</div>
<p>Wrong answer</p>
</radio-div>
<radio-div v-model="politicalParty" val="Democrat">
<div class="text-h6">Democrat</div>
<p>Wrong answer</p>
</radio-div>
<radio-div v-model="politicalParty" val="Independent">
<div class="text-h6">Independent</div>
<p>These people clearly know what's up</p>
</radio-div>
</q-card-section>
</q-card>
</div>
</template>
<script lang="ts">
import Vue, Component, Watch from "vue-property-decorator";
import RadioDiv from "../components/RadioDiv.vue";
@Component(
components: RadioDiv
)
export default class Profile extends Vue
politicalParty = "Independent";
</script>
这按预期工作。我可以点击<div>
s,它会切换选择哪一个并适当地更新变量。
但现在我想将它与全局状态管理器联系起来。因此,我有一个 computed 属性,而不是本地 politicalParty
变量:
<script lang="ts">
import Vue, Component, Watch from "vue-property-decorator";
import RadioDiv from "../components/RadioDiv.vue";
import globalState from "../globalState";
@Component(
components: RadioDiv
)
export default class Profile extends Vue
get politicalParty()
return globalState.politicalParty;
set politicalParty(val)
globalState.politicalParty = val;
</script>
将console.log
语句放入设置器中,我可以看到它正在被调用,并且变量正在被更新。但是在我的value
观察程序(在RadioDiv
组件中)中添加console.log
语句表明它现在不再被调用,因为我正在使用计算属性。
既然我正在使用全局状态,那么让我的 RadioDiv
再次响应的秘诀是什么?
更新
这个问题似乎并不特定于我的自定义组件或观察者。我决定忽略这一点,继续等待 *** 的回答,然后再次遇到 Quasar 组件的问题:
<template>
...
<q-card-section>
<div class="row">
<div class="col">
<q-slider v-model="age" :min="0" :max="100" />
</div>
<div class="col">
ageText
</div>
</div>
</q-card-section>
...
</template>
<script lang="ts">
...
get age()
return globalState.age;
set age(val)
globalState.age = val;
this.ageText = "You are " + val + " years old";
...
</script>
这导致我尝试不使用任何自定义组件:
<template>
...
<input type="text" v-model="test" />
<p>Text: test </p>
...
</template>
<script lang="ts">
let testVal = "";
...
get test() return testVal;
set test(val) testVal = val;
...
</script>
再一次:没有反应。当我使用带有v-model
的计算属性时,调用set
后似乎没有任何变化
【问题讨论】:
【参考方案1】:如果globalState
只是一个Object
,那么它不会是反应式的,所以computed
只会读取它的值一次。 testVal
也一样,它只是一个 String
(本身也不是响应式的)。
要使 test
计算的 prop 响应于 testVal
,请使用 Vue.observable()
创建 testVal
:
const testVal = Vue.observable( x: '' )
@Component
export default class Profile extends Vue
get test() return testVal.x
set test(val) testVal.x = val
与globalState
类似,导出Vue.observable()
将使您的计算道具具有反应性:
// globalState.js
export default Vue.observable(
politicalParty: ''
)
【讨论】:
以上是关于TypeScript VueJS:使用具有计算属性的观察器的主要内容,如果未能解决你的问题,请参考以下文章