vue.jsvuejs3

How to use data from export component in class?


I got a class, that was defined in the same Component File, but out of scope for the data, that i am exporting. I'd like to simply call the function, that was defined inside the "export default", but as i am doing, I'm getting the following error, as the map function is not inside the scope:

Test.vue?t=1751457112648:55 Uncaught TypeError: this.map is not a function` -

That is the file i am working with:

<template>
</template>
<script>
class SimpleTest {
  pong() {this.map();}
}
export default {
  name: 'Test',
  data() {
    return {
      init: false,
    }
  },
  methods: {
    map() {return "Simple Return";},
  },
  mounted() {
    let simpleOne = new SimpleTest();
    simpleOne.pong();
  }
}
</script>

Solution

  • Accessing a scope outside a class suggests there's a potential problem with class design. This could be written in several different ways.

    This would be a quickfix that doesn't solve the design problem:

    simpleOne.pong.call(this);
    

    Generally a class or a method needs to be injected with a function or object. This could be simple but this contradicts the principle of least privilege and gives instance to the whole this instance:

    class SimpleTest {
        constructor(instance) {
          this.instance = instance;
        }
        pong() {
          this.instance.map();
        }
    }
    ...
    let simpleOne = new SimpleTest(this);
    simpleOne.pong();
    

    It's a better design to give it the access to the exact part of the instance it needs. Component methods are bound to the instance and can be passed as callbacks:

    class SimpleTest {
        pong(map) {
          map();
        }
    }
    ...
    let simpleOne = new SimpleTest();
    simpleOne.pong(this.map);
    

    This isn't a good use case for classes because SimpleTest is stateless, and map doesn't make use of component instance. This could be achieved with plain functions:

    function map() {...}
    
    function pong() { ping() }
    

    In case map uses component instance and pong needs to be declared outside a component, reusable functionality can be put to a mixin with options API:

    let testMixin = {
      methods: {
        pong() {
          this.map();
        }
    }
    ...
    mixins: [testMixin],
    methods: {
      map() {...},
    },
    

    This would be designed differently with composition API through composables.