Maison  >  Article  >  interface Web  >  Vue peut-elle modifier la valeur dans prop ?

Vue peut-elle modifier la valeur dans prop ?

WBOY
WBOYoriginal
2022-06-16 10:29:324570parcourir

Vous ne pouvez pas modifier directement la valeur de prop dans vue. Si vous modifiez directement vue, un avertissement sera généré, et la modification de la valeur de la propriété ne peut pas modifier la variable correspondant au composant parent cependant, vous pouvez déclencher l'événement du composant enfant, et le composant parent écoutera l'événement et l'exécutera. Modifiez la fonction du composant parent et réalisez une liaison de données bidirectionnelle en écoutant les événements du composant enfant pour modifier la valeur dans l'accessoire.

Vue peut-elle modifier la valeur dans prop ?

L'environnement d'exploitation de ce tutoriel : système Windows 10, version Vue3, ordinateur Dell G3.

Vue peut-elle modifier la valeur dans prop ?

Dans Vue, prop peut accepter les attributs transmis des composants parents aux composants enfants, mais prop ne peut pas être modifié.

Si un accessoire est modifié de force, il y aura un avertissement

Tous les accessoires forment une liaison descendante unidirectionnelle entre leurs accessoires parent et enfant : Les mises à jour des accessoires parent circuleront vers le bas vers les composants enfants, mais vice versa Non . Cela empêchera le composant enfant de modifier accidentellement l'état du composant parent, ce qui rendrait le flux de données de votre application difficile à comprendre.

De plus, chaque fois que le composant parent change, tous les accessoires du composant enfant seront actualisés avec les dernières valeurs. Cela signifie que vous ne devez pas modifier les accessoires à l'intérieur d'un composant enfant. Si vous faites cela, Vue émettra un avertissement dans la console du navigateur.

Essayez de modifier directement la valeur de l'attribut via la méthode suivante

this.$props.modelValue = true;

Vue émettra un avertissement

L'opération de définition sur la clé « modelValue » a échoué : la cible est en lecture seule.

Et la modification de la valeur de l'attribut ne peut pas modifier la variable correspondante au composant parent, s'applique uniquement aux types de données de base.

Notez qu'en JavaScript, les objets et les tableaux sont transmis par référence, donc pour un accessoire de type tableau ou objet, La modification de l'objet ou du tableau lui-même dans le composant enfant affectera l'état du composant parent, et Vue ne peut pas avertir vous à ce sujet . En règle générale, vous devez éviter de modifier des accessoires, y compris des objets et des tableaux, car cela ignore la liaison de données unidirectionnelle et peut conduire à des résultats inattendus.

Vue3 Props Document

La méthode de modification correcte consiste à déclencher l'événement du composant enfant. Le composant parent écoute l'événement et exécute la fonction qui modifie le composant parent. Prenez v-model comme exemple. , v-model lui-même est l'attribut modelValue transmis au composant enfant, puis écoute l'événement update:modelValue pour obtenir v-model 为例,v-model 本身就是传递给子组件的 modelValue 属性,然后监听 update:modelValue 事件来做到双向数据绑定,所以我们也可以通过该方法来在代码中修改 modelValue

this.$emit("update:modelValue", !this.$props.modelValue);

v-model 将自动监听 update:modelValue 事件并将 modelValue 修改为触发事件时传递的参数值(即 $emit 的第二个参数)。

需要注意的是,这种通过触发事件-监听事件的数据流模式并不能马上生效,如果使用以下代码

this.$emit("update:modelValue", !this.$props.modelValue);console.log(this.$props.modelValue);

会发现输出到控制台的仍然是 modelValue 原先的值,这是因为触发事件-监听事件的模式下属性值的修改需要时间,改用以下代码会发现输出正常:

this.$emit("update:modelValue", !this.$props.modelValue);setTimeout(()=> {console.log(this.$props.modelValue)}, 1000)

实践

由于 Vant 只实现了左边放 label 的输入框,想基于此实现一个 label 在右边的输入框

Vant3 Field 文档

这其中遇到的问题除了把 label 右置并根据 label 的内容自适应宽度外,就是 Vant 中的 <van-field /> 与我需要实现的 <right-label-input /> 以及放置 <right-label-input> 的父组件之间的数据流了。

错误做法

为了能够与 <van-field /> 一致使用 v-model ,我在 <right-label-input /> 下设置 modelValue 属性,然后将 <van-field>v-model="modelValue"

<template>
<van-field :placeholder="placeholder" :name="name" v-model="modelValue" :disabled="disabled"/>
</template>

<script>
export default {
    name: "RightLabelInput",
    props: {
        modelValue: "",
    },
}
</script>

无疑,这种做法违背了单向数据流原则,在 VanField 修改时将直接影响 RightLabelInputmodelValue 值,而 modelValueRightLabelInputdeux- manière de liaison de données

, nous pouvons donc également utiliser cette méthode pour modifier modelValue

<template>
    <van-field :placeholder="placeholder"
               :name="name"
               v-model="input"

               :disabled="disabled"
    />
</template>

<script>
export default {
    name: "RightLabelInput",
    props: {
        placeholder: "",
        name: "",
        label: "",
        modelValue: "",
        disabled: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {
            input: this.modelValue, // 绑定到 data 的变量,防止直接修改 Props
        }
    },
    beforeMount() {
        this.input = this.modelValue
    },
    watch: {
        input(newInput, oldInput) {
            this.$emit("update:modelValue", newInput); // 监听 input 在修改时发起事件,由父组件修改 modelValue 的值
        },
        modelValue(newValue, oldValue) {
            this.input = newValue;
        }
    }
}
</script>

<style scoped>

</style>

v-model écoutera automatiquement le update:modelValue événement et remplacez-le par modelValue Modifier la valeur du paramètre transmise lorsque l'événement est déclenché (c'est-à-dire le deuxième paramètre de $emit).

Il convient de noter que ce mode de flux de données de déclenchement d'événements et de surveillance des événements ne prend pas effet immédiatement si vous utilisez le code suivantrrreee

, vous constaterez que la sortie vers la console est toujours modelValuecode> valeur d'origine, cela est dû au fait qu'il faut du temps pour modifier la valeur de l'attribut en mode événement déclencheur-écoute. Si vous utilisez le code suivant, vous constaterez que la sortie est normale : <p>rrreee<a href="https://www.php.cn/vuejs/" target="_blank">Pratique</a></p>Depuis Vant uniquement. implémente <code>label sur la zone de saisie de gauche, je souhaite implémenter un label basé sur cette zone de saisie à droite🎜🎜Document Vant3 Field🎜🎜Les problèmes rencontrés dans ce domaine sont d'ailleurs en plaçant label à droite et selon label, il s'agit du <van-field /> dans Vant et le <right-label-input /&gt que je dois implémenter. Les données circulent entre ; et le composant parent où <right-label-input> est. mis. 🎜🎜Mauvaise approche🎜🎜Pour pouvoir utiliser v-model de manière cohérente avec <van-field />, j'ai utilisé <right-label- input / > Définissez l'attribut modelValue sous <van-field> 🎜Cette approche viole sans aucun doute le principe du flux de données unidirectionnel lorsque <. code>VanField est modifié, cela affectera directement la valeur modelValue de RightLabelInput, et modelValue est une propriété de RightLabelInput et ne peut pas être modifié directement. 🎜🎜Peut-être la bonne approche🎜rrreee🎜🎜Mots clés🎜 : Flux de données unidirectionnel🎜🎜[Recommandation associée : "🎜tutoriel vue.js🎜"]🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn