Vuejs: How do I read a src attribute that is already within a v-html directive?

Asked

Viewed 70 times

2

The contents contained in the string videosOnScreen is transformed into HTML by the directive v-html, but cannot find the path of the attribute src.

Is there any way this attribute can be read?

<template>
    <div class="media" v-html="videoPlaying"></div>
</template>


<script>
export default {
    data() {
        return {
            videoPlaying: "",
        };
    },
    async mounted() {
        console.log(await this.getPlayersInfo());        
    },
    methods: {    
        async getPlayersInfo() {
            videoWidth = 500
            videoHeight = 300

            videosOnScreen = '<video muted width="' + videoWidth + '" height="' + videoHeight + '" autoplay src="../../assets/video/first-video.mp4"></video>'
            this.videoPlaying = videosOnScreen
        }
    }
}
  • Does it not load the video or does it not render the component? OBS: Voce should declare the variables using const

  • They are declared, I did not put this part of the code. It renders the video, I can see the video black screen in one position, but the video doesn’t start, the screen only turns black.

1 answer

3


In the above case, the src thus "../../assets/video/first-video.mp4", because in the end, this is not the path that Vuejs uses to serve the static files.

For example, in a project of mine, I have a file .png inside assets, but if I inspect the page’s HTML, the image is being served from another directory, in my case, the src of hers is /img/gmblogoatual.4caa3f41.png. See that begins by /img and not /assets or ../../assets, at last.

As you want to generate an HTML element through a string, first we have to import the file that will be referenced in the src.

How do we do that?

Using the require('...') to import the file inside assets.

In your code, we’ll do the following:

  1. After videoPlaying, let’s declare a variable called videoUrl that will make the import video file and receive the link (path or path) relative to the video file. In function data:
return {
        videoPlaying: "",       // ↓↓↓↓↓↓↓↓↓ aquele seu caminho fica no "require"
        videoUrl: require("../../assets/video/first-video.mp4"),
};
  1. Let’s work with the function getPlayersInfo. I’ll use string template for easy reading. Where you used to src="../../assets/video/first-video.mp4", let’s do it this way:
async getPlayersInfo() {
  const videoWidth = 500;
  const videoHeight = 300;

  this.videoPlaying =
    `<video width="${videoWidth}" controls height="${videoHeight}" autoplay src="${this.videoUrl}"></video>`;
},

See that now on src I passed the value of this.videoUrl. This variable is that will be responsible for solving (thanks to Vuejs) the path that should be used to serve the video file.

I don’t think you need to change anything else in your code. See how it would look:

<template>
  <div class="media" v-html="videoPlaying"></div>
</template>

<script>
  export default {
    data() {
      return {
        videoPlaying: '', // ↓↓↓↓↓↓↓↓↓ aquele seu caminho fica no "require"
        videoUrl: require('../../assets/video/first-video.mp4')
      };
    },
    async mounted() {
      await this.getPlayersInfo(); // retirei o console.log
    },
    methods: {
      async getPlayersInfo() {
        const videoWidth = 500;
        const videoHeight = 300;

        this.videoPlaying = `<video width="${videoWidth}" controls height="${videoHeight}" autoplay src="${this.videoUrl}"></video>`;
      }
    }
  };
</script>

After the archive tests, recreating the conditions of your code, this was my result when inspecting the final page HTML:

inserir a descrição da imagem aqui

Notice that even import of assets, the final path was to src="/media/first-video.9684e373.mp4", because Vuejs generates other folders and saves the files in them to serve in the final build.

Notice also that he generated a id unique to the static file served (first-video.9684e373.mp4).


Heed

Use the directive v-html cautiously. Use it only with content controlled and managed by you, because if it is dependent on unknown content, it can create serious problems and loopholes for attacks XSS, as described and alerted by the documentation itself:

Dynamically Rendering arbitrary HTML on your website can be very Dangerous because it can easily lead to XSS Attacks (Opens new window). Only use v-html on Trusted content and Never on user-provided content.

  • Thank you very much, man. I had already tried using require, but by putting it directly into src from inside the video string, it ended up not working. My only problem at the moment is that the videos (I’m using the string inside a repeat structure now) appear on the screen before being loaded, so one ends up appearing before the other. Do you know any features or suggestions that I can use for the template only to render the videos after they are uploaded? Either way, they fight.

  • I may have an idea of how to do it, but since this is another problem, you would have to create a new question, post the relevant code, images of how it appears, etc....

  • I just posted my question in case I can help

Browser other questions tagged

You are not signed in. Login or sign up in order to post.