最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - vue.js firing $emit not received by $on - Stack Overflow

programmeradmin5浏览0评论

Vueponent('rating-edit', {
    template:`
    <form>
      <input v-model="rating.title" type="text">
      <textarea v-model="rating.remark">{{rating.remark}}</textarea>
      <button type="button"
        @click="submit">
        Save
      </button>
    </form>`,
    props:['rating'],
    methods: {
      submit: function submit () {
        let rating = this.rating;
        this.$emit('submit', rating);
        console.log('submit was emitted');
      }
    }
  });

const aRating = {
    title: 'title',
    remark: 'remark'
  };

let vueApp = new Vue({
    el: '#rating-edit-container',
    data: {
      rating: aRating
    }
  });

vueApp.$on('submit', function(rating) {
  console.log('vue on submit', rating);
});
<script src=".min.js"></script>
<div id="rating-edit-container">
  <rating-edit :rating="rating"></rating-edit>
</div>

Vue.ponent('rating-edit', {
    template:`
    <form>
      <input v-model="rating.title" type="text">
      <textarea v-model="rating.remark">{{rating.remark}}</textarea>
      <button type="button"
        @click="submit">
        Save
      </button>
    </form>`,
    props:['rating'],
    methods: {
      submit: function submit () {
        let rating = this.rating;
        this.$emit('submit', rating);
        console.log('submit was emitted');
      }
    }
  });

const aRating = {
    title: 'title',
    remark: 'remark'
  };

let vueApp = new Vue({
    el: '#rating-edit-container',
    data: {
      rating: aRating
    }
  });

vueApp.$on('submit', function(rating) {
  console.log('vue on submit', rating);
});
<script src="https://vuejs/js/vue.min.js"></script>
<div id="rating-edit-container">
  <rating-edit :rating="rating"></rating-edit>
</div>

In a legacy frontend code I'd like implement a vue based ponentized form and have it return the data on submit.

This is the ponent code. Please note the submit function firing this.$emit('submit', rating);

let result = {
  props:['rating'],
  methods: {
    submit: function submit () {
      let rating = this.rating;
      this.$emit('submit', rating);
      console.log('submit fired');
    }
  }
};

export default result;

And now in the legacy code, I am waiting for the events:

import Vue from 'vue';
import ratingEditVue from './rating-edit.vue';


Vue.ponent('rating-edit', ratingEditVue);

const aRating = {
  title: 'title',
  remark: 'remark'
};

let vueApp = new Vue({
  el: '#rating-edit-container',
  data: {
    rating: aRating
  }
});

vueApp.$on('submit', function(rating) {
  console.log('vue on submit', rating);
});

As far as I understand the Vue events this should work. But $on('submit', handlerFunction) just never gets called.

Addendum:

I've fiddled the example. I apologize for not having done this in the first place.

Share Improve this question edited Jul 18, 2017 at 13:06 LongHike asked Jul 18, 2017 at 11:53 LongHikeLongHike 4,4608 gold badges50 silver badges86 bronze badges 2
  • Can you provide any plete fiddle for your case? – donMateo Commented Jul 18, 2017 at 12:04
  • 2 You are $emiting in a child ponent and setting up $on to catch events in the parent. $on catches events emitted in the current Vue (think of an event bus), so have the parent set it up on the child. – Roy J Commented Jul 18, 2017 at 12:58
Add a ment  | 

2 Answers 2

Reset to default 11

The issue is that you are emitting along the same scope depth of your rating-edit ponent.

If you instead emit to the parent with this.$parent.$emit, the event will be received by the parent. Note, if you need to do this in multiple places or at multiple depths, you want to use an event bus instead.

Vue.ponent('rating-edit', {
    template:`
    <form>
      <input v-model="rating.title" type="text">
      <textarea v-model="rating.remark">{{rating.remark}}</textarea>
      <button type="button"
        @click="submit">
        Save
      </button>
    </form>`,
    props:['rating'],
    methods: {
      submit: function submit () {
        let rating = this.rating;
        this.$parent.$emit('submit', rating);
        console.log('submit was emitted');
      }
    }
  });

const aRating = {
    title: 'title',
    remark: 'remark'
  };

let vueApp = new Vue({
    el: '#rating-edit-container',
    data: {
      rating: aRating
    }
  });

vueApp.$on('submit', function(rating) {
  console.log('vue on submit', rating);
});
<script src="https://vuejs/js/vue.min.js"></script>
<div id="rating-edit-container">
  <rating-edit :rating="rating"></rating-edit>
</div>

vueApp.$on('submit', function(rating) {
  console.log('vue on submit', rating);
});

Your handler here will only be executed in response to submit events emitted from vueApp directly (i.e. vueApp.$emit('submit')), which I don't think is happening in your code (which isn't fully provided).

Vue events do not bubble.

Suppose your #rating-edit-container template is something like this:

<template id="rating-edit-container">
  <div>
    <rating-edit @submit="onRatingSubmit"></rating-edit>
  </div>
</template>

Then you should have your handler (onRatingSubmit) declared in the methods of your ponent like this:

let vueApp = new Vue({
  el: '#rating-edit-container',
  methods: {
    onRatingSubmit(rating) {
      console.log('rating submit', rating);
    },
  },
});

EDIT

You still have the same issue as what I described. I modified your snippet by removing the emission on $parent instead of this and registering the listener on the <rating-edit> element in the template.

Vue.ponent('rating-edit', {
    template:`
    <form>
      <input v-model="rating.title" type="text">
      <textarea v-model="rating.remark">{{rating.remark}}</textarea>
      <button type="button"
        @click="submit">
        Save
      </button>
    </form>`,
    props:['rating'],
    methods: {
      submit: function submit () {
        let rating = this.rating;
        this.$emit('submit', rating);
        console.log('submit was emitted');
      }
    }
  });

const aRating = {
    title: 'title',
    remark: 'remark'
  };

let vueApp = new Vue({
    el: '#rating-edit-container',
    data: {
      rating: aRating
    },
    methods: {
      onSubmit(rating) {
        console.log('vue on submit', rating);
      },
    },
  });
<script src="https://vuejs/js/vue.min.js"></script>
<div id="rating-edit-container">
  <rating-edit :rating="rating" @submit="onSubmit"></rating-edit>
</div>

发布评论

评论列表(0)

  1. 暂无评论