javascriptvue.jsvuejs2createjspreloadjs

Cannot load assets more than once with PreloadJS and Vue.js


I am trying to create a Vue.js component which would allow me to load (using PreloadJS) and display various EaselJS canvas experiments. The Vue.js component:

  1. Gets created with a HTML canvas and 2 divs for experiment scripts and the EaselJS library
  2. created lifecycle hook: Loads the EaselJS library using PreloadJS (included in the main HTML file)
  3. Stores the EaselJS lib files in the #creatjLib div
  4. Afterwards it loads the experiment script files and stores them in #gameAssets

Here is the component:

<template>
  <div class="fullscreen">
    <canvas id="canvas" class="fill"></canvas>
    <div id="createjsLib" class="hidden"></div>
    <div id="gameAssets" class="hidden"></div>
  </div>
</template>

<script>
  import {createjsList} from '../../assets/lists/games.js'
  import {manifests} from '../../assets/conf.js'

  export default {
    props: ['id'],
    data() {
      return {
        game: createjsList[this.id],
        queue: new createjs.LoadQueue()
      };
    },
    methods: {
      onLibrariesLoaded() {
        var lib = this.queue.getResult("EaselJS");
        var libCont = document.getElementById("createjsLib");
        libCont.innerHTML = "";
        libCont.appendChild(lib);

        document.getElementById('gameAssets').innerHTML = "";
        var manifest = (this.game.manifest) ? this.game.manifest : '/static/games/' + this.id + '/manifest.json';
        this.queue = new createjs.LoadQueue();
        this.queue.on("complete", this.onGameAssetsLoaded);
        this.queue.on("fileload", this.onGameAssetLoaded);
        this.queue.loadManifest(manifest);
      },
      onGameAssetLoaded(e) {
        var type = e.item.type;
        if (type == createjs.LoadQueue.CSS || type == createjs.LoadQueue.JAVASCRIPT) {
          document.getElementById('gameAssets').appendChild(e.result);
        }
      },
      onGameAssetsLoaded() {
        console.log('Assets Loaded');
      }
    },
    created() {
      var manifest = manifests.createjs;
      this.queue.on("complete", this.onLibrariesLoaded);
      this.queue.loadManifest(manifest);
      console.log('created');
    }
  }
</script>

The Problem

My problem is that this process only works once. I can load the EaselJS library and the experiments files only once, the scripts get correctly executed but once I navigate (vue-router, history mode) home for example and then back to the experiment it fails to even load the library again and crashes in the created lifecycle hook.

Error in created hook: "TypeError: Cannot read property 'observeArray' of undefined"

Console log

I tried using the destroyed and beforeDestroy lifecycle hooks to cancel, delete, reset the PreloadJS queue but nothing I tried works. The error seems to happend somewhere in Vue.js but I am not sure why or how to fix this. I have checked the manifest url and it points to the correct static JSON manifest file.

Any ideas what's going on? What have I missed here? Any advice/help will be appreciated


Solution

  • This line: queue: new createjs.LoadQueue() is likely the culprit. Vue.js requires that all properties of its data object be primitive values or plain objects.

    You can create an instance of createjs.LoadQueue inside your created() hook and save it to some internal property on your component. A common convention is to make it something like this.$createjsQueue. Up to you.

    data() {
        return {
            game: createjsList[this.id],
            queue: null
        }
    },
    created() {
        this.$createJsQueue = new createjs.LoadQueue()
    
        // Expose some internal value of the instance
        this.queue = this.$createJsQueue._queue
    }