即使分配给同一个 newVal 也如何触发观察者

问题描述 投票:0回答:1

我正在使用

vue3
options api

如下所示

stackbiltz
链接这里

我有一个包含

button
的子组件,单击该子组件时,应调用
refresh
方法。
refresh()
true
设置为
event-emitter
,如下面的代码所示。 在父组件中,我通过
event-emitter
绑定在
v-model
上,如下面的代码所示,这样,正如我所期望的,每次单击按钮
refresh
时,都会看到变量
vModel
的主体父组件应该被执行。 但发生的情况是,只有第一次单击按钮
refresh
时,才会执行父级中的监视变量
vModel

为了解决这个问题,我使用了

$forceUpdate
但没有效果。

我知道这种行为的原因是在子组件中的

refresh()
中总是将
true
设置为
this.compPropsVmodel
而不更改分配给它的值,但我不知道如何解决这个问题

父组件:

<template>
    <Child
      v-model:vModel="vModel">
    </Child>
</template>

<script>
import Child from './components/Child.vue'

export default {
  name: 'App',
  data() {
        return {
          vModel: false,
        };
  },
  components: {
    Child
  },
  watch: {
    vModel(newVal, oldVal) {
      console.log('@watch vModel');
    },
  },
}
</script>

子组件:

<template>
    <button
        id="idBtnRefreshCalendar"
        type="button"
        @click="refresh">
        refresh
    </button>
</template>

<script>
let debugTag = 'D.Child.vue::';
let infoTag = 'I.Child.vue::';
let verboseTag = 'V.Child.vue::';
let warnTag = 'W.Child.vue::';
let errorTag = 'E.Child.vue::';
let WTFTag = 'WTF.Child.vue::';
//
export default {
    name: 'Child',
    data() {
        return {
        };
    },
    components: {},
    props: {
        vModel: {
            type: null,
        },
    },
    emits: {
        'update:vModel': null,
    },
    computed: {
        compPropsVModel: {
            get() {
                console.log('get.compPropsVModel:', this.vModel);
                return this.vModel;
            },
            set(value) {
                console.log('set.compPropsVModel:', value);
                this.$emit('update:vModel', value);
            },
        },
    },
    methods: {
        refresh() {
            const msg = JSON.stringify({ msg: verboseTag + 'refresh():'});
            console.log(msg);
            this.compPropsVModel = true;
            this.$forceUpdate();
        },
    },
};
</script>
vue.js vuejs2 vuejs3 vue-component
1个回答
0
投票

您似乎期望

watch
在不更改观看值的情况下被触发。好吧,不要,因为这不是
watch
的设计目的。仅当值更改时才会触发。 调用
$forceUpdate
强制对组件运行检查(除了组件自己的触发器之外)以确保值没有更改。因为还没有,
watch
回调将不会被执行。

如果您允许进行更丰富多彩的比较,则期望在不更改值的情况下触发它就像将衣物放入搅拌机并期望其发挥洗衣机的作用一样。不要,因为它不会。


要从子函数触发父函数(方法)的执行,可以使用以下方法:

  • a) [推荐👍] - 将方法作为事件向下传递 (
    @someName="parentMethod"
    )。在子组件中,将其添加到
    emits
    :
export default {
  emits: ['someName']
}

       ...并使用

this.$emit('someName', ...args)
调用它,这将触发
每次都在父级中
parentMethod(...args)
。不需要
v-model
watch

  • b) [不推荐 👎] - 将方法向下传递为
    prop
    (
    :someName="parentMethod"
    ) 并将其称为
    this.someName(...args)
    。它有效,但您可能会遇到范围问题(
    this
    可能并不总是当前组件实例,这就是不推荐的原因)。
© www.soinside.com 2019 - 2024. All rights reserved.