javascript 与子组件通信时,使用哪种方法更好- $emit还是$ref?

avkwfej4  于 2023-01-29  发布在  Java
关注(0)|答案(1)|浏览(132)

请告诉我。有一个用于更改用户数据的页面。此页面包含用于输入用户信息的字段和一个"提交"按钮。我需要创建一个执行相同功能的弹出式组件。表单本身现在将位于子组件中。"提交"按钮现在移动到父组件中。因此, 我需要把输入的数据传递给父组件,因为最初的数据来自服务器,有用户的预先输入信息,所以最初需要通过props把数据传递给子组件。然后在从子节点修改的时候,再传递给父节点,但是如果变量很多怎么办,比如:我需要创建15个props,然后通过$emit传递这个数据,数据本身通过标签的@input事件或者标签的@change事件传递,我想到了三个选项,但是我不知道哪个更好,或者有些根本不应该使用。 tag or the @change event of the tag. I thought of three options, but I don't know which one is better. Or maybe some should not be used at all.
1.* * 使用$emit**
父组件

<template>
  <Child 
    :first-props="user.first"
    :second-props="user.second"
    ....
    :fifteenth-props="user.fifteenth"
  />
  <button @click='submit'>Submit</button>
</template>

<script>
import Child from '@/components/Child.vue'
import { mapGetters } from 'vuex'
export default {
  data: () => ({
    first: '',
    second: '',
    ...
    fifteenth: ''
  }),
  components: {
    Child
  },
  computed: {
    ...mapGetters({
      user: 'user/getUser'
    })
  },
  methods: {
    submit() {
     //Sending data
    }
  },
  mounted: {
    this.$store.dispatch('user/getUserData')
  }
}
</script>

子组件

<template>
  <div>
    <input type="text" value="first" @input="username" />
    <input type="text" value="second" @input="name" />
    <input type="text" value="fifteenth" @input="surname" />
  </div>
</template>

<script>
export default {
  props: {
    first: {
      type: String,
      required: true
    },
    first: {
      type: String,
      required: true
    },
    ...
    fifteenth: {
      type: String,
      required: true
    }
  },
  methods: {
    username() {
     this.$emit('changeUsername', first)
    },
    name() {
     this.$emit('changeName', second)
    },
    surname() {
     this.$emit('changeSurname', fifteenth)
    }
  }
}
</script>

在这个变体中,我担心 prop 的数量。我不知道这是否会以某种方式影响组件的速度和质量。
1.* * 使用$ref**
父组件

<template>
  <Child 
    ref='childComponent'
  />
  <button click="submit">Submit</button>
</template>

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

export default {
  data: () => ({
    first: '',
    second: '',
    ...
    fifteenth: ''
  }),
  components: {
    Child
  },
  method: {
    submit() {
      this.$refs.childComponent.submit()
    }
  }
}
</script>

子组件

<template>
  <div>
    <input type="text" v-model="first" @input="username" />
    <input type="text" v-model="second" @input="name" />
    <input type="text" v-model="fifteenth" @input="surname" />
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
export default {
  data: () => ({
    first: '',
    second: '',
    ...
    fifteenth: ''
  }),
  computed: {
    ...mapGetters({
      user: 'user/getUser'
    })
  },
  methods: {
    submit() {
     //Sending data
    }
  },
  mounted: {
    this.$store.dispatch('user/getUserData')
  }
}
</script>

在这个变体中,父组件和子组件之间没有太多的交互,父组件只触发submit方法,另外,你不需要对现有代码做太多的修改,因为你只需要移动按钮,但是这里我担心的是:用这种方式应用ref不是一个糟糕的决定吗?第二个问题是当按钮被点击时数据的可用性。更有可能的是子组件还没有接收到必要的数据或者只是还没有加载,而用户已经按下了按钮。例如,父组件已经有一个主标题和一个提交按钮。2但是子组件仍然在加载。尽管这里的解决方案可以是使用:disabled ="isDisabled"使按钮仅在加载子组件后才可按。
1.* * 使用vuex**
这个选项在我看来是错误的,因为数据只在这个组件内部使用,而且vuex在我看来只适合全局情况。
我已经尝试了所有三个选项,它们都工作。但我希望代码不仅工作,而且是正确的。

0g0grzrc

0g0grzrc1#

$ref$emit的用途不同,通常在它们之间没有选择。
选项1可以在子对象中使用单个数据属性:

<input
  type="text"
  :value="formData.first"
  @input="$emit('updateFormData', { key: 'first', value: $event.target.value }))"
/>

并合并父项中的更改:

<Child 
    :formData="formData"
    @updateFormData="formData[$event.key] = $event.value"
  />

选项2在当前状态下是可行的。或者,子级可以是自包含的,并包含提交按钮,那么$ref就没有用了。如果有与表单提交相关的业务逻辑不应该移动到子级,它可以发出submit事件。
选项3是可能的,但是将全局存储用于本地目的是不合理的,可以使用Vuex动态模块实现本地存储。

相关问题