javascript - typescript VueJS : Using watcher with computed property

标签 javascript typescript vue.js vuejs2

我正在构建一个允许我使用任意 <div> 的自定义组件作为单选按钮。目前我的代码如下所示:

<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 并切换选择哪个并适本地更新变量。

但现在我想将其绑定(bind)到一个全局状态管理器中。所以而不是本地 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我可以看到它正在 被调用,并且正在更新变量。但是放一个 console.log我的声明 value观察者(在 RadioDiv 组件中)显示它不再被调用,因为我正在使用计算属性。

获得我的 RadioDiv 的秘诀是什么?再次响应,现在我正在使用全局状态?

更新

这个问题似乎不是我的自定义组件或观察者所特有的。我决定忽略这一点并继续等待 StackOverflow 的回答,并在使用 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 后似乎没有任何变化

最佳答案

如果 globalState 只是一个 Object,那么它不会是响应式(Reactive)的,所以 computed 只会读取它的值一次testVal 也一样,它只是一个 String(本身也不是响应式(Reactive)的)。

要使 test 计算属性对 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() 将允许您计算的 Prop 是 react 性的:

// globalState.js
export default Vue.observable({
  politicalParty: ''
})

关于javascript - typescript VueJS : Using watcher with computed property,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64988299/

相关文章:

typescript - 使用 fetch api 处理 500 响应

javascript - RxJs - 具有 Observable 属性的 FlatMap 对象

javascript - Vue 单元测试 : Using Functions imported Incorrectly into a Component

javascript - 如何合并/推送 Javascript 数组中的重复值

javascript - 组合 Chrome 异步 API

javascript - 如何调整 html Canvas 元素的大小?

typescript - 如何导入使用此给定导出构造导出的函数?

javascript - 如何使用 css/js 为表中的每一行创建不同长度的列?

javascript - 正则表达式 - 在 AngularJS 指令中包含空格

javascript - 正则表达式如何匹配日期时间字符串特定字符的前2个实例