слушать события из динамических компонентов VUE - PullRequest
1 голос
/ 30 мая 2019

Как бы вы прослушали событие, генерируемое динамически созданным экземпляром компонента?

В этом примере верхний компонент добавляется в DOM, а второй динамически создается в javascript.

Vue.component("button-counter", {
  data: function() {
    return {
      count: this.initial_count
    }
  },
  props: ['initial_count'],
  methods: {
    add: function() {
      this.count++
        this.$emit('myevent', this.count)
    }
  },
  template: '<button v-on:click="add">You clicked me {{ count }} times.</button>'
})

let app = new Vue({
  el: "#app",
  data() {
    return {
      initial_count: 10,
    }
  },
  mounted: function() {
    let initial_count = this.initial_count

    let ButtonCounterComponentClass = Vue.extend({
      data: function() {
        return {}
      },
      render(h) {
        return h("button-counter", {
          props: {
            initial_count: initial_count
          }
        })
      }
    })
    let button_counter_instance = new ButtonCounterComponentClass()
    button_counter_instance.$mount()
    button_counter_instance.$on('myevent', function(count) {
      console.log('listened!')
      this.say(count)
    })
    this.$refs.container.appendChild(button_counter_instance.$el)
  },
  methods: {
    say: function(message) {
      alert(message)
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

<div id="app">
    <button-counter initial_count=20 v-on:myevent="say"></button-counter>
    <div ref='container'></div>
</div>

1 Ответ

2 голосов
/ 30 мая 2019

Если я понял, что вы хотите, тогда вам просто нужно прослушать событие на внутреннем компоненте и передать его.

Я использовал функции стрелок в нескольких местах, чтобы избежать проблем с привязками this. В противном случае я попытался оставить ваш код без изменений в максимально возможной степени. Изменения отмечены ****.

Vue.component("button-counter", {
  data: function() {
    return {
      count: this.initial_count
    }
  },
  props: ['initial_count'],
  methods: {
    add: function() {
      this.count++
        this.$emit('myevent', this.count)
    }
  },
  template: '<button v-on:click="add">You clicked me {{ count }} times.</button>'
})

let app = new Vue({
  el: "#app",
  data() {
    return {
      initial_count: 10,
    }
  },
  mounted: function() {
    let initial_count = this.initial_count

    let ButtonCounterComponentClass = Vue.extend({
      data: function() {
        return {}
      },
      render(h) {
        return h("button-counter", {
          props: {
            initial_count: initial_count
          },
          // **** Added this ****
          on: {
            myevent: count => {
              this.$emit('myevent', count);
            }
          }
          // ****
        })
      }
    })
    let button_counter_instance = new ButtonCounterComponentClass()
    button_counter_instance.$mount()
    // **** Changed the next line ****
    button_counter_instance.$on('myevent', count => {
      console.log('listened!')
      this.say(count)
    })
    this.$refs.container.appendChild(button_counter_instance.$el)
  },
  methods: {
    say: function(message) {
      alert(message)
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

<div id="app">
    <button-counter initial_count=20 v-on:myevent="say"></button-counter>
    <div ref='container'></div>
</div>

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

Документы, которые вы можете передать h: https://vuejs.org/v2/guide/render-function.html#The-Data-Object-In-Depth

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...