简体   繁体   中英

Adding Events to Dynamically rendered HTML in Vue.js Component

I'm trying to dynamically render some HTML in a Vue.js component. I'm successfully rendering the HTML. However, I don't know how to wire-up the events for the dynamically rendered elements. I've created a small example. This example probably looks like I've over complicated things. However, it's just a small part of the real example. The example can be seen in this JSFiddle , and the code looks like this:

new Vue({
  el: '#app',
  data: {
    items: [
      { 
        name:'Item 1', 
        isHtml:true, 
        mold: function() {
          return '<button @click="onButtonOneClick">click</button>';
        }
      },

      {
        name: 'Item 2',
        isHtml: false
      },

      {
        name:'Item 3',
        isHtml: true,
        mold: function() {
          return '<button @click="onButtonThreeClick">click</button>';
        }
      }
    ]
  },

  methods: {
    getHtml: function(i) {
      return i.mold();
    },

    onButtonOneClick: function() {
      alert('First Item Clicked');
    },

    onButtonThreeClick: function() {
      alert('Third Item Clicked')
    }
  }
})

If you run this fiddle, you'll notice that my two buttons look fine on the screen. However, the related click events don't get fired when you actually click the buttons. From what I can see, it looks like the HTML doesn't get fully compiled. I may be wrong. But, it's what it looks like based on what i see in the Chrome Dev Tools.

How do I wire up events for dynamically generated HTML in a Vue.js component?

I'm sorry to be a nuisance, but why have you got vue markup in your data : ? This is never going to work. Can you explain what led you down this path? Why can't your markup stay in a template : ?

Vue does have a v-html directive for popping little bits of markup out of javascript into templates, but Vue tags in this markup are not processed, and it's one of those features you should use with a bad conscience.

Event listeners outside of Vue, attached after Vue has rendered, do function, but then you've really got to look at yourself in the mirror and ask "oh what have I done" ?

Your example goes against everything that Vue is trying to accomplish. I suggest reading up on Vue in their docs or following some tutorials. I am not saying it can't be done because you could certainly bind events later but it is not wise.

Certainly something like this is not going to work:

mold: function() {
  return '<button @click="onButtonThreeClick">click</button>';
}

That is because Vue has already rendered the markup when you inject this.

It is difficult to tell what you are trying to achieve exactly but perhaps something like this can help you out:

https://jsfiddle.net/ozf8kq1z/2/

(Open your console)

You're trying to render 'functional html' which is basically the essence of what Vue does for you. Just render your list as you do, and add in your data in an attribute like 'is_button', and output the html for the button in the v-for and add its events. eg

   <div v-for="(item, index) in items">
    <button v-if="item.is_button" @click="onButtonClick(index)">
    <div>item.content</div>
   </div>

Good luck

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM