пользовательское событие ($ emit) в VueJS - PullRequest
0 голосов
/ 14 мая 2019

У меня проблема с использованием $emit в VueJS.Я получил эту ошибку:

[Vue warn]: избегайте прямого изменения свойства, так как значение будет перезаписываться при повторном рендеринге родительского компонента.Вместо этого используйте данные или вычисляемое свойство, основанное на значении реквизита.Подставка изменена: "userAge"

Родитель:

<template>
  <div class="component">
    <h1>The User Component</h1>
    <p>I'm an awesome User!</p>
    <button @click="changeName">Change my name</button>
    <p>Name is {{ name }}</p>
    <hr>
    <div class="row">
      <div class="col-xs-12 col-sm-6">
        <app-user-detail 
          :myName="name" 
          :resetNameParent="resetNameFn"
          @nameWasReset="name = $event"
          :userAge="age"
        ></app-user-detail>
      </div>
      <div class="col-xs-12 col-sm-6">
        <app-user-edit 
          :userAge="age"
          @ageWasEdited="age = $event"
        ></app-user-edit>
      </div>
    </div>
  </div>
</template>

<script>
import UserDetail from './UserDetail.vue';
import UserEdit from './UserEdit.vue';

export default {
  data() {
    return {
      name: 'Max',
      age: 27
    }
  },
  methods: {
    changeName() {
      this.name = 'Anna'
    },
    resetNameFn() {
      this.name = 'Max';
    },
  },
  components: {
    appUserDetail: UserDetail,
    appUserEdit: UserEdit
  }
}
</script>

<style scoped>
div {
  background-color: lightblue;
}
</style>

Ребенок:

<template>
  <div class="component">
    <h3>You may edit the User here</h3>
    <p>Edit me!</p>
    <p>User Age: {{ userAge }}</p>
    <button @click="editAge">Edit Age</button>
  </div>
</template>

<script>
export default {
  props: ['userAge'],
  methods: {
    editAge() {
      // this.userAge = 30; - przestarzałe
      // this.$emit('ageWasEdited', this.userAge);  - przestarzałe
      this.$emit('ageWasEdited', 30);
    }
  }
}
</script>

<style scoped>
div {
  background-color: lightgreen;
}
</style>

Я прочитал руководство, но не смог правильно реализовать решение,

Как мне избежать этой ошибки?

1 Ответ

0 голосов
/ 15 мая 2019

Любое значение, переданное как prop, прослушивается компонентом, который его получает. Таким образом, если родитель изменяет это значение, дочерняя версия будет иметь свою собственную измененную версию, перезаписанную новым значением родителя. Это может привести к неожиданному поведению. Лучше иметь копию значения в любое время, когда оно изменяется. Например, вы можете использовать свойство «watched»:

{
    props: [ "userAge" ],
    data: function() {
        return {
            myUserAgeCopy: null
        };
    },
    watch: {
        userAge: function() {
            this.myUserAgeCopy = this.userAge;
        }
    }
}

Затем все дальнейшие операции выполняются на myUserAgeCopy.


Обратите внимание, что приведенное выше по-прежнему приводит к той же проблеме перезаписи данных, что и при прямом изменении prop. Важно то, что теперь эта перезапись сделана явной и предсказуемой благодаря тому, как вы написали код.


В общем, если вам нужно синхронизировать родитель и потомок, вы всегда должны $emit вносить изменения на уровне ребенка, разрешать родителю принимать эти изменения, а затем получать $emit изменения в потомке через оригинал prop:

child: {
    props: [ "userAge" ],
    data: function() {
        return {
            myUserAgeCopy: null
        };
    },
    watch: {
        userAge: function() {
            this.myUserAgeCopy = this.userAge;
        },
        myUserAgeCopy: function() {
            this.$emit('user_age_changed', this.myUserAgeCopy);
        }
    }
}

parent: {
    data: function() {
        return {
            userAge: 30
        };
    },
    methods: {
        handleUserAgeChange: function(userAge) {
            this.userAge = userAge;
        }
    }
}

<child :userAge="userAge" v-on:user_age_changed="handleUserAgeChange"/>
...