Skip to content
Advertisement

Watch for async external DOM changes in Vue

I am injecting ads from Revive Adserver with this component:

<template>
 <div class="ins-box">
  <ins ref="insEl" :data-revive-zoneid="zoneId" data-revive-id="hash"></ins>
 </div>
</template>

<script>
export default {
  props: {
    zoneId: { type: String, default: '' }
  },
}

The external api from Revive Adserver will load the ad image for the zone (in the example zone 1234), converting the <ins> element:

<ins zone-id="1234" />

The <img> tag it creates looks something like this:

<ins data-v-fdd5803a="" data-revive-zoneid="7859">
 <a href="http://servedby.revive-adserver.net/ck.php?params" target="_blank">
  <img src="https://www.source.com/image-555.jpg" width="468" height="60" alt="" title="" border="0">
 </a>
</ins>

I would like to edit the created <img> element when it is added into the DOM. I would need to remove the width and height values.

In jQuery I could do something like $('ins img').load(function() {})

What is the Vue way to do this? The element is not created by my Vue code and I don’t have reference to it. On top of that the there might come a new <img> element now and them.

Advertisement

Answer

You could solve this with pure CSS, for example using an attribute selector. Setting the image’s height and width to auto should be the equivalent of removing the HTML attributes.

Here’s an example that will style all images inside <a> tags having an href with the ad server domain.

a[href*="revive-adserver.net"] img{
  height: auto;
  width: auto;
}

If you insist on doing this with JavaScript, use a mutationObserver on the element’s parent to detect external DOM changes to its children. Give the parent a ref:

<div ref="ins-box" class="ins-box">

Create the mutation observer:

mounted() {
  const observer = new MutationObserver((mutationsList, observer) => {
    const img = this.$refs['ins-box'].querySelector('img');
    img.onload = () => {
      // Now do something with `img`
    }
  });
  observer.observe(this.$refs['ins-box'], { childList: true });
}

The reason for watching for changes on the parent instead of the element itself is the element might be completely replaced by the external service.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement