【问题标题】:custom event ($emit) in VueJSVueJS 中的自定义事件 ($emit)
【发布时间】:2019-10-01 22:41:17
【问题描述】:

我在 VueJS 中使用 $emit 时遇到问题。我收到了这个错误:

[Vue 警告]:避免直接改变 prop,因为每当父组件重新渲染时,该值都会被覆盖。相反,使用基于道具值的数据或计算属性。正在变异的道具:“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>

我阅读了手册,但无法正确实施解决方案。

我怎样才能避免这个错误?

【问题讨论】:

  • 我不认为你分享的代码会给你这个错误。 this.userAge = 30 行已被注释掉,但肯定会导致该错误。那是有问题的代码行吗?或者您是说您看到共享的代码有错误?
  • 是的,我遇到了这样的错误,这让我很吃惊。这是 STRING,所以它不会传递指针,只是在 console log 对中创建一个新变量@

标签: javascript vue.js events emit


【解决方案1】:

作为prop 传递的任何值都被接收它的组件“监听”。因此,如果父级修改此值,则子级将使用父级的新值覆盖其自己的修改版本。这可能导致意外行为。更好的做法是在值发生更改时保留其副本。例如,您可以使用“watched”属性:

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

然后所有进一步的操作都在myUserAgeCopy 上执行。


请注意,上述操作仍会导致与直接更改 prop 相同的数据覆盖问题。重要的是,现在这种覆盖通过您编写代码的方式变得明确且可预测。


一般来说,如果你需要保持父子同步,你应该始终$emit任何子级的更改,让父级接受这些更改,然后通过$emitted 接收子级的更改原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"/>

【讨论】:

    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2020-02-17
    • 2018-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多