【问题标题】:2 Way Databind components within Components2 Way Databind 组件内的组件
【发布时间】:2022-01-01 20:46:51
【问题描述】:

我正在努力重用我的组件。

我想将传递给我的组件的数据作为道具传递给另一个组件。
如果我这样做,vue 会抱怨道具的突变。

示例: 我想在我的应用的多个位置显示联系人。
为此,我创建了一个联系人组件来重用它:

<template>
    <div>
        <input :value="contact.firstName" @input="$emit('update:contact', {...contact, firstName: $event.target.value})">
        <Mother v-model:mother="contact.mother"/>
    </div>
</template>

<script>
import Mother from '@/components/Mother'

export default {
  name: 'Contact',
  components: {
    Mother
  },
  props: {
    contact: Object,
  },
  emit: ['update:contact'],
  methods: {
  }
}
</script>

每个联系人都有一个母亲,母亲不仅在联系人组件中显示在其他地方。 这就是为什么我创建了一个母组件,供联系人使用。

<template>
    <div>
        <input :value="mother.lastName" @input="$emit('update:mother', {...mother, lastName: $event.target.value})">
    </div>
</template>

<script>
export default {
  name: 'Mother',
  props: {
    mother: Object,
  },
  emit: ['update:mother'],
  methods: {
  }
}
</script>

现在我希望能够同时改变母亲的联系人,并且我希望能够在同一个站点上使用两个联系人组件。

如果我按照解释的方式使用它,我会收到此错误:

 ERROR  Failed to compile with 1 error                                  09:17:25

 error  in ./src/components/Contact.vue

Module Error (from ./node_modules/eslint-loader/index.js):

/tmp/vue-example/src/components/Contact.vue
  4:27  error  Unexpected mutation of "contact" prop  vue/no-mutating-props

✖ 1 problem (1 error, 0 warnings)

我有一个示例项目显示我的问题: https://gitlab.com/FirstWithThisName/vue-example.git

感谢您的帮助

【问题讨论】:

  • 您的项目正在运行。更详细地写下你不能做的事情
  • 不,不是,如果您尝试使用 npm run serve 运行它,您会收到错误“接触”道具的意外突变'
  • 正如它所说的,你不能改变一个道具。您应该查看使用 v-model 时自动传入的“modelValue”道具。并使用 watch/computed 属性而不是直接改变 prop 来跟踪更新的值。另外我没有看到链接 2 个输入组件的原因,为什么不将 2 个不同的组件拆分为“App.vue”呢?
  • @Cerceis 在另一个地方重用链接的组件。

标签: vue.js vuejs3


【解决方案1】:

取决于您的应用程序的复杂程度。 一种选择是双向数据绑定,如此处所述: https://v3.vuejs.org/guide/component-basics.html#using-v-model-on-components

所以你基本上emit对父级的更改。

对于更复杂的应用程序,我不会将多个组件中使用的数据作为道具传递,而是使用存储。要么是一个简单的反应对象;要么使用provide/inject 或使用Vuex 之类的东西。

【讨论】:

  • 我不能通过 emit 两次,或者我不知道怎么做。我认为vuex不是正确的选择,不是为全局状态管理而生的吗?提供/注入接缝对我也很不利,因为我必须对名称进行硬编码,所以我不能在同一个父级中使用我的组件两次。
  • @AceofSpade 发射两次有什么问题?如果您已经尝试过这样做,在问题中显示这一点可能有助于解决它,而不是从头开始解释整个概念。
【解决方案2】:

首先我需要假设几点。

  • 您想使用 v-model。
  • 您希望将组件链接起来。

Vue SFC Playground 上的工作示例 here
*请注意,示例站点上的导入路径不同。

App.vue

<template>
    <Contact v-model="contact" />
    {{ contact }}
</template>
... remaining code omitted 

联系.vue

<template>
    <div>
        <input v-model="localValue"/>
        <Mother v-model="childValue" />
    </div>
</template>

<script>
import Mother from "./Mother.vue"
export default {
    name: "Contact",
    components: {
        Mother
    },
    props: {
        modelValue: Object,
    },
    mounted(){
        this.childValue = this.modelValue.mother
    },
    data: () => ({
        localValue: "",
        childValue: null
    }),
    watch:{
        updatedData(){
            this.$emit('update:modelValue', this.updatedData)
        }
    },
    computed: {
        updatedData() {
            return { firstName: this.localValue, mother: this.childValue };
        },
    },
};
</script>

母亲.vue

<template>
    <div>
        <input
            v-model="localValue"
            @input="$emit('update:modelValue', updatedData)"
        />
    </div>
</template>

<script>
export default {
    name: "Mother",
    props: {
        modelValue: Object,
    },
    data: () => ({
        localValue: "",
    }),
    computed: {
        updatedData() {
            return { ...this.modelValue, lastName: this.localValue };
        },
    },
};
</script>

您可能知道,props 不能被变异,因此您需要“复制”每个组件上的值以在本地处理。

如果Mother组件永远不会单独使用,v-model可以拆分为v-onv-bind

最后,关于推荐,如果数据开始增长或深度级别增加,这样的链接可能会变得非常混乱。您可以只创建另一个 Wrapper 组件,其中包含水平缩放的 ContactMother 组件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-21
    • 1970-01-01
    • 2017-02-01
    • 2017-01-04
    • 1970-01-01
    • 2010-12-15
    • 2018-11-27
    • 2018-07-11
    相关资源
    最近更新 更多