在不使用发射的情况下跟踪父级中的子组件值?

Posted

技术标签:

【中文标题】在不使用发射的情况下跟踪父级中的子组件值?【英文标题】:Keep track of child component values in parent without using emit? 【发布时间】:2021-09-29 05:58:13 【问题描述】:

我有一个名为HobbyForm 的自定义组件,它是一个带有两个控件、一个复选框和一个输入的简单表单,该组件是从一个名为Content 的父组件以及其他类似的“表单”组件调用的。

<template>
    <form>
       <div class="row align-items-center">
            <div class="col-1">
                <Checkbox id="isHobbyActive" :binary="true" v-model="isActive"/>
            </div>
            <div class="col-5">
                <InputText id="hobby" placeholder="Hobby" type="text" autocomplete="off" v-model="hobby"/>
            </div>
        </div> 
    </form>
</template>
<script>
export default 
    name: 'HobbyForm',
    data() 
        return 
            hobby: 
                isActive: false,
                hobby: null
            
        
    ,

</script>

我的内容组件类似于:

<template>
    <language-form></language-form>
    <hobby-form v-for="(hobbie, index) in hobbies" :key="index" v-bind="hobbies[index]"></hobby-form>
    <Button label="Add Hobby" @click="addHobby"></Button>
</template>
<script>

export default 
  name: "Content",
  components: 
    LanguageForm,
    HobbyForm
  ,
  data() 
    return 
      language: '',
      hobbies: [
        
          isActive: false,
          hobby: null
        
      ]
    ;
  ,
  methods: 
      addHobby() 
        this.hobbies.push(
          isActive: false,
          hobby: null
        );
      
  ,
;
</script>

这个想法是能够添加更多HobbyForm 组件的实例,以将另一个爱好记录添加到我的hobby 数据属性;但我不知道如何在我的子组件中不使用emit 的情况下从我的父级跟踪这些值,因为我不想手动触发发射,我只想在我的父级中更新数据组件。

我应该如何从我的父组件访问我的子组件的数据并将其添加到我的数组中?

【问题讨论】:

【参考方案1】:

在当前表单中,通过v-bind="hobbies[index]" 将父数据传递到子组件是没有意义的,因为子组件 (HobbyForm) 没有 props,因此它不会从父组件接收任何数据...

使其工作:

    从子 HobbyForm 中删除 data() 改为声明Object 类型的道具 将表单项绑定到该对象的属性 将对象传递到每个HobbyForm
<template>
    <form>
       <div class="row align-items-center">
            <div class="col-1">
                <Checkbox id="isHobbyActive" :binary="true" v-model="hobby.isActive"/>
            </div>
            <div class="col-5">
                <InputText id="hobby" placeholder="Hobby" type="text" autocomplete="off" v-model="hobby.hobby"/>
            </div>
        </div> 
    </form>
</template>
<script>
export default 
    name: 'HobbyForm',
    props: 
      hobby: 
        type: Object,
        required: true
      
    

</script>

即使道具被设计为one way only,所以孩子不应该改变道具值,这是另一回事,因为你不改变道具值,你正在改变(通过v-model)通过传递的对象的属性一个道具(参见单向数据流段落底部的注释)

还将父级更改为:

<hobby-form v-for="(hobby, index) in hobbies" :key="index" v-bind:hobby="hobby"></hobby-form>

演示:

const app = Vue.createApp(
  data() 
    return 
      hobbies: [
        isActive: false,
        hobby: null
      ]
    ;
  ,
  methods: 
    addHobby() 
      this.hobbies.push(
        isActive: false,
        hobby: null
      );
    
  ,
)

app.component('hobby-form', 
  props: 
    hobby: 
      type: Object,
      required: true
    
  ,
  template: `
  <form>
       <div class="row align-items-center">
            <div class="col-1">
                <input type="checkbox" id="isHobbyActive" v-model="hobby.isActive"/>
            </div>
            <div class="col-5">
                <input type="text" id="hobby" placeholder="Hobby" autocomplete="off" v-model="hobby.hobby"/>
            </div>
        </div> 
    </form>
  `
)

app.mount('#app')
<script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script>
<div id='app'>
   <hobby-form v-for="(hobby, index) in hobbies" :key="index" v-bind:hobby="hobby"></hobby-form>
   <button @click="addHobby">Add Hobby</button>
   <hr/>
   <pre>  hobbies  </pre>
</div>

【讨论】:

好的,我做了你提到的更改,但我仍然无法让它工作;我不太清楚,使用这个解决方案我应该能够输入每个HobbyForm 的输入,并在我的父组件的hobbies 数组中的相应项目中更新该值? 是的,我认为我的 linter 不允许我这样做,因为它将它解释为我试图改变 prop,并且不会编译 错误信息?我不认为这是 linter 应该标记为 prop 突变的东西,因为它不是。事实上,我在带有 ESLint 的成熟 Vue CLI 项目中使用它没有任何问题。 the rule 也没有将其列为不良示例... 我同意,但是即使我复制/粘贴您的代码,它也会在我这边引发错误,我会检查我的 linter 规则,如果我让它工作,我会回复你

以上是关于在不使用发射的情况下跟踪父级中的子组件值?的主要内容,如果未能解决你的问题,请参考以下文章

从父级中的子级访问元素标记名

如何使用Vue从父级中的多个子组件中获取值?

在不增加会话数的情况下跟踪 Android 中的后台事件的好方法是啥?

我应该或可以为父级中的子解析器获取数据吗?

如何在不调用事件的情况下将数据从子级发送到父级(vue 2)

javascript 从父级中的子级渲染节点更新