在 vue 3 中查看父组件的子属性

Posted

技术标签:

【中文标题】在 vue 3 中查看父组件的子属性【英文标题】:Watch child properties from parent component in 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,而只是注意变化。

谢谢!

【问题讨论】:

为什么不想发出事件? 因为我想了解如何观察跨组件变化的数据。计数只是一个例子。这不是一个奇特的案例,但不幸的是我没有得到任何结果,所以这就是我问的原因。 【参考方案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 链访问。

【讨论】:

以上是关于在 vue 3 中查看父组件的子属性的主要内容,如果未能解决你的问题,请参考以下文章

vue解决父组件调用子组件只执行一次问题

VUE:组件与组件之间的通信

vue父子组件之间props的数据通信

vue 组件通信 (子传父 , 父传子 , 兄弟通信)

vue组件路由事件

vue组件之间传值常用