Vue.js - 如何在数据对象更改时向父组件发出?

Posted

技术标签:

【中文标题】Vue.js - 如何在数据对象更改时向父组件发出?【英文标题】:Vue.js - How to emit to parent component on change in data object? 【发布时间】:2021-01-06 13:48:42 【问题描述】:

使用v-model 在组件内的视图和数据模型之间创建双向绑定。并且视图交互可以向父组件发出事件。

但是,有可能让子组件中的数据模型更改向父组件发出事件吗?

因为只要用户是单击复选框的人,父母和孩子的事情都很好(数据模型更新并发出事件)。但是,如果我打开 Vue 开发工具并切换子组件数据中的复选框,来自v-model 的双向绑定将在 CHILD 组件中进行适当的更新,但没有任何东西可以将其转移到父组件(我怀疑是因为没有发出事件)。

如何确保父组件“知道”子组件中的数据更改?我认为这必须以某种方式实现......如果不是从子组件发出,也许有某种方法可以让父组件“监视”子组件的数据?

感谢您的帮助或指导!在此期间,我会继续阅读并寻找答案!

子组件

<template>
  <div class="list-item" v-on:click="doSomething">
    <input type="checkbox" v-model="checked">
    <label v-bind:class=" checked: checked "> name </label>
  </div>
  ...
</template>

<script>
  ...
  data: function() 
    return 
      checked: false,
    
  ,
  methods: 
    doSomething() 
      ...
      this.$emit('doSomething', this)
    
  
</script>

父组件

<template>
  <ChildComponent v-on:doSomething="getItDone"></ChildComponent>
  ...
</template>

<script>
  ...
  methods: 
    getItDone(target) 
      ...
    
  
</script>  

更新:在尝试了更多@IVO GELOV 的解决方案之后,我现在遇到的问题是,当涉及多个子组件时,由于父级的 myBooleanVar 的一个奇异值驱动整个事情,选中一个子组件的框会导致所有子组件被选中。

因此,在视图和数据操作都将其移交给父级方面,这绝对是一个进步,但我仍在试图弄清楚如何“隔离”这种情况,以便只有一个被操作的子组件被拖动参加聚会...

【问题讨论】:

【参考方案1】:

也许您可以使用v-bind="$attrs"直接将复选框属性绑定到父属性

看看这个答案:https://***.com/a/56226236/10514369

【讨论】:

感谢@davidr 的链接!连同 Ivo 的帖子,这两篇文章都很好地帮助我了解了 Vue 的可能性!【参考方案2】:

你可以将数据保存在parent中,作为prop提供给child,让child观察prop并更新它的内部状态,最后当child的内部状态已经被触发时向parent发出一个事件改变了。

父母

<template>
  <ChildComponent v-model="myBooleanVar" />
  ...
</template>

<script>
  data()
  
    return 
      myBooleanVar: false,
    
  ,
  watch:
  
    myBooleanVar(newValue, oldValue)
    
      if (newValue !== oldValue) this.getItDone(newValue);
    
  ,
  methods: 
  
    getItDone(value) 
    
      ...
    
  
</script>  

孩子

<template>
  <div class="list-item">
    <input type="checkbox" v-model="checked">
    <label :class=" checked: checked "> name </label>
  </div>
  ...
</template>

<script>
  props:
  
    value:
    
      type: Boolean,
      default: false
    
  
  data() 
  
    return 
      checked: this.value,
    
  ,
  watch:
  
    value(newVal, oldVal)
    
      // this check is mandatory to prevent endless cycle
      if(newVal !== oldVal) this.checked = newVal;
    ,
    checked(newVal, oldVal)
    
      // this check is mandatory to prevent endless cycle
      if(newVal !== oldVal) this.$emit('input', newVal);
    
  ,
</script>

【讨论】:

你好@IVO GELOV!谢谢!所以,只是为了确保我遵循它在做什么......而不是让数据值“活”在子组件中并尝试将其状态 UP 传递给父组件,而是以不同的方式进行。它在 Parent 中具有数据值的“实时”状态,将其传递给 Child,然后,每当 Child 中的值发生更改时,由于 watch: 行为,任何值更改都会将 $emited 返回给 Parent .因此,在某种程度上,父级“共享”其数据以供子级使用。我正确地遵循了吗?哇!多么美妙的解决方案! @IVO_GELOV 有没有办法让它不被所有子组件通用?每当我与单个 Child 交互时,所有 Child 组件复选框最终都会被切换。在我的 OP 底部添加了更新。 当您有多个孩子时 - 您应该在父级中使用多个布尔变量,每个孩子一个。当然,除非您有意同时驱动所有复选框:) 您好 IVO!是的,我将应用程序的整个结构更改为不使用布尔值作为主要驱动程序。现在它就像一个魅力!是什么让你的回答对我来说“点击”是阅读关于从 Vue 2 升级到 3 的 Vue 文档(尽管这不是我感兴趣的事情)。这显示了父/子结构中的内容,现在文档的其余部分更有意义!再次感谢您的帮助!

以上是关于Vue.js - 如何在数据对象更改时向父组件发出?的主要内容,如果未能解决你的问题,请参考以下文章

发出的事件不会调用 Vue JS 组件中的父方法

Vue.js中子组件向父组件传递信息。

Vue.js组件的通信之子组件向父组件的通信

将 vue.js 组件子中的对象或值发送到父通信

如何在 Vue 中向父布局槽发出事件?

Vuejs 3 从子组件向父组件发出事件