VueJS中的自定义事件($ emit)

时间:2019-05-14 20:39:42

标签: javascript vue.js events emit

在VueJS中使用void mainImage( out vec4 fragColor, in vec2 fragCoord ) { // Normalized pixel coordinates (from 0 to 1) vec2 uv = fragCoord/iResolution.xy; // read the histogram data from a sampler // on shadertoy there are no 1D textures, so we use a // single row of a 2D texture instead, and sweep up/down // over time to get a "dynamic" histogram. vec3 h = texture(iChannel0, vec2(uv.x, sin(0.01*iTime))).rgb; // discard fragments which are "outside" the histogram // also use this value later for the alpha channel float a = smoothstep( 0.000, 0.001, length(h)); if( 0. == a ){ discard; } // Color the fragment. The smoothstep gives some antialiasing. // For perfect pixel coverage based antialiasing we'd have to // determine the slope of the histogram, to construct a tangent // and determine the distance to it, i.e. create a // Signed Distance Field fragColor = vec4( smoothstep(-0.001, 0.001, h.r - uv.y), smoothstep(-0.001, 0.001, h.g - uv.y), smoothstep(-0.001, 0.001, h.b - uv.y), a ); // Instead of using the smoothstep and/or the SDF using a // multisampled buffer and performing a simple `y >= h` test // would yield probably a nicer result. } 时遇到问题。我收到此错误:

  

[Vue警告]:避免直接更改道具,因为每当父组件重新渲染时,该值就会被覆盖。而是使用基于属性值的数据或计算属性。道具被突变:“ userAge”

父母:

$emit

孩子:

<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>

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

如何避免此错误?

1 个答案:

答案 0 :(得分:0)

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

{
    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"/>