2
votes

SOLVED (Almost): Delete <div v-if="isFrameLoaded"> and binding src data to <video>. Now it loads at the same time that request is sent (no data in getBLOB but then it reloads itself (no need to manually save files). It remains a mystery why this specific v-if doesn't work for me. Thank you guys!.

Edited Frame.vue

      //This is needed
<video v-bind:src="getBLOB"> 
           //Here too
    <source v-bind:src="getBLOB" type="video/mp4" />
    Your browser does not support the
</video>

EDIT:

state: {
...,
isFrameLoaded: false
}

Getters from the store content.js

getters:{
...,
isFrameLoaded: state => state.isFrameLoaded
}

mutations

mutations: {
...,
SAVE_ISFRAMELOADED(state, boolean) {
      state.isFrameLoaded = boolean;
      console.log("frame loaded");
    },
}

Things I tried: binding :key, this.$forceUpdate(), <keep-alive>


The problem is that <div v-if="isFrameLoaded"> is checked before the resource is downloaded (isFrameLoaded == false), some time later the resource will be download and the computed property should return true from the $store.getters, but what I see is that the computed property is never called again, even after updating its state.

I have made it before and it works as expected. The unique difference is that Home.vue is a view and Frame.vue is a component, $store works.

This doesn't work Frame.vue

<template>
...
    <div v-if="isFrameLoaded">
        <video>
           <source v-bind:src="getBLOB" type="video/mp4" />
        </video>
    </div>
</template>
<script>
export default {
  computed: {
    isFrameLoaded() {
    //this is called just once
      console.log("isFrameLoaded()");
      return this.$store.getters["content/isFrameLoaded"];
    }
  }
};
</script>

This works Home.vue , "list" is a component.vue


<template>
...
    <template v-if="childDataLoaded">
        <list />
    </template>
</template>
<script>
export default {
  name: "Home",
  computed: {
    childDataLoaded() {
      return this.$store.getters["content/isThumbnailLoaded"];
    }
    }
  
};
</script>

This is where isFrameLoaded is modified contentstore.js

getFrameBlob({ commit, state }) {
      commit("SAVE_ISFRAMELOADED", false); //HERE
      return contentService
        .getBigImg()
        .then(response => {
          var url = URL.createObjectURL(
            new Blob([response.data], { type: state.frame.mediaType })
          );
          commit("SAVE_CURRENTBLOB", url);
          commit("SAVE_ISFRAMELOADED", true); //HERE
          return url;
        });
    },

And this method modifies the condition that works (isThumbnailLoaded)

getThumbnails({ commit, state }) {
      commit("SAVE_ISTHUMBNAILLOADED", false); //HERE
      state.home.imgs.forEach((thumbnail, i) => {
        contentService
          .getThumbImg()
          .then(response => {
            var url = URL.createObjectURL(new Blob([response.data]));
            commit("SAVE_THUMBFRAME", {
              key: state.home.frames[i],
              value: url,
              like: state.home.likes[i]
            });
            if (state.thumbFrame.length == state.home.imgs.length) {
              commit("SAVE_ISTHUMBNAILLOADED", true); //HERE
            }
          });
      });
      return;

I notice that if I delete the v-if from Frame.vue the source its not loaded (image type always load but video type doesn't) at first try, but if I update and save the project while it is running now video resources also loads.

So.. Any hints? I read about nextTick() function but it seems too complex just for that, I also curious about why modifying project's files while running it solves the bug.

Thank you!

1
did you check Vue DevTool, the state=isFrameLoaded is updated correctly?Sphinx
Yes, but it seems something else is not working, once I see the video on browser (after saving files while running) if I want to see another video resource I have to modify and save files again, despite of Vue DevTool shows state always correctly updated.addUsername

1 Answers

0
votes

You actually do not need to create a computed properties. Store getters already are reactive.

The way you are wrapping the getter in the computed prop is not making the computed prop reactive because getters, like computed properties are actually methods which are just implicitly executed when referred. If you actually log the computed prop like:

console.log('Getter: ', this.$store.getters["content/isThumbnailLoaded"]);

You will see that this will log a method rather than the value that you are expecting.

You can use mapGetters to map your getter to the computed props in your component.

import { mapGetters } from 'vuex';

  export default {
    computed: {
      ...mapGetters({
        isFrameLoaded: 'content/isFrameLoaded',
      }),
    }
  };

or if you want to continue with this approach, you can do something like this:

export default {
  computed: {
    isFrameLoaded() {
      //this is called just once
      console.log("isFrameLoaded: ", this.$store.getters["content/isFrameLoaded"]());
      return this.$store.getters["content/isFrameLoaded"]();
    }
  }
};

I would still suggest to use the first method, that is more readable and cleaner.

Regards.