【问题标题】:Watch child properties from parent component in vue 3在 vue 3 中查看父组件的子属性
【发布时间】:2021-05-23 23:25:09
【问题描述】:

我想知道如何使用组合 api 从 Vue 3 中的父组件观察子属性(我正在使用实验性 script setup)。

<template>//Child.vue
  <button 
    @click="count++" 
    v-text="'count: ' + count" 
  />
</template>

<script setup>
import { ref } from 'vue'

let count = ref(1)
</script>
<template>//Parent.vue
  <p>parent: {{ count }}</p> //update me with a watcher
  <Child ref="childComponent" />
</template>


<script setup>
import Child from './Child.vue'
import { onMounted, ref, watch } from 'vue'

const childComponent = ref(null)
let count = ref(0)

onMounted(() => {
  watch(childComponent.count.value, (newVal, oldVal) => {
    console.log(newVal, oldVal);
    count.value = newVal
  })
}) 
</script>

我想了解如何从父组件观察子组件的变化。我不工作的解决方案受到Vue.js 2 Solution asked here 的启发。所以我不想发出count.value,而只是注意变化。

谢谢!

【问题讨论】:

  • 为什么不想发出事件?
  • 因为我想了解如何观察跨组件变化的数据。计数只是一个例子。这不是一个奇特的案例,但不幸的是我没有得到任何结果,所以这就是我问的原因。

标签: vue.js vue-component vuejs3 vue-composition-api vue-script-setup


【解决方案1】:

&lt;script setup&gt; 内部的绑定“默认关闭”,如您所见 here

但是,您可以显式公开某些参考。 为此,您使用useContext().expose({ ref1,ref2,ref3 })

所以只需将其添加到 Child.vue:

import { useContext } from 'vue'

useContext().expose({ count })

然后将Parent.vue中的Watcher改为:

watch(() => childComponent.value.count, (newVal, oldVal) => {
    console.log(newVal, oldVal);
    count.value = newVal
  })

而且它有效!

【讨论】:

  • 你的两个建议都没有效果。 childComponent.value.count 未定义。我知道它是通过发射和道具解决的。正如我所说,我对这个例子很感兴趣。
  • 您是否更改了 Child.vue 中的代码?从&lt;script setup&gt; import { ref } from 'vue' let count = ref(1) &lt;/script&gt; &lt;script&gt; import { ref } from 'vue'; export default { setup(){ const count = ref(1) return { count } } } &lt;/script&gt; ?它对我有用。
  • 使用script setup 方法似乎还无法实现您尝试做的事情。查看 RFC github.com/vuejs/rfcs/blob/script-setup-2/active-rfcs/… 中的这个主题(默认关闭)。其目的是绑定不会在父组件中公开。注意:“如何显式公开命令式公共接口将在github.com/vuejs/rfcs/pull/210 中完成。”
  • 我已经编辑了我的回复,已经有一种方法可以使用&lt;script setup&gt; 语法公开引用!
  • 工作正常,谢谢。我希望你也会使用脚本设置(当它最终获得批准时)
【解决方案2】:

我已回复Vue 2 Solution 它与 Vue 3 完美配合如果您不使用 script setup 或显式公开属性

这是工作代码。

Child.vue

<template>
  <button @click="count++">Increase</button>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    return {
      count: ref(0),
    };
  },
};
</script>

Parent.vue

<template>
  <div id="app">
    <Child ref="childComponent" />
  </div>
</template>

<script>
import { ref, onMounted, watch } from 'vue';
import Child from './components/Child.vue';

export default {
  components: {
    Child,
  },
  setup() {
    const childComponent = ref(null);

    onMounted(() => {
      watch(
        () => childComponent.value.count,
        (newVal) => {
          console.log({ newVal }) // runs when count changes
        }
      );
    });

    return { childComponent };
  },
};
</script>

See it live on StackBlitz


请继续阅读

Vue 2 Solution 中我已经描述了我们应该使用mounted hook 以便能够观察子属性。 然而,在 Vue 3 中,这不再是问题/限制,因为观察者有额外的选项,如 flush: 'post',可确保元素已被渲染。

请务必阅读Docs: Watching Template Refs


使用script setup 时,组件的公共实例不会暴露,因此 Vue 2 解决方案将不起作用。 为了使其工作,您需要显式公开属性:

使用脚本设置

从 'vue' 导入 { ref } 常数 a = 1 常量 b = ref(2) 定义暴露({ 一种, b })

使用选项 API

export default {
  expose: ['publicData', 'publicMethod'],
  data() {
    return {
      publicData: 'foo',
      privateData: 'bar'
    }
  },
  methods: {
    publicMethod() {
      /* ... */
    },
    privateMethod() {
      /* ... */
    }
  }
}

注意:如果您在 Options API 中定义 expose,那么只有那些属性会被公开。其余部分将无法从模板引用或 $parent 链访问。

【讨论】:

    猜你喜欢
    • 2020-09-30
    • 2021-12-27
    • 2019-04-20
    • 2022-12-04
    • 2018-01-03
    • 2021-08-02
    • 2021-06-03
    • 1970-01-01
    • 2021-07-26
    相关资源
    最近更新 更多