The right way to access a Vue variable from a class method

Viewed 572

Here is my code:

<div id='R'> {{ y.vmx() }} </div>

<script>
    class Test {
      vmx() {
        return vm.x
      }
    }

    var vm = new Vue({
      el: '#R',
      data: {
        x: 11,
        y: new Test()
      }
    })
</script>

This error pops up: TypeError: Cannot read property 'x' of undefined at Test.vmx ((index):18)

How can I access a Vue variable inside a class method? (Vue v2.6.11)

1 Answers

In this case, the template is loaded before vm is assigned, so vm is undefined in the Test class. Ideally, this circular dependency should be avoided in your code design, but there are a couple workarounds.

OPTION 1: Defer any references to vm inside Test until after the initial template is loaded.

For example, set a ready flag in the next tick after the component has mounted, and then use the flag to conditionally render the template parts that require access to vm:

class Test {
  vmx() {
    return vm.x
  }
}

var vm = new Vue({
  el: '#app',
  data: () => ({
    x: 2,
    y: new Test(),
    ready: false,
  }),
  async mounted() {
    await this.$nextTick()
    this.ready = true
  }
})
<script src="https://unpkg.com/vue@2.6.11/dist/vue.min.js"></script>

<div id="app">
  <p v-if="ready">{{ y.vmx() }}</p>
</div>

OPTION 2: Pass a reference to the vm when instantiating Test

class Test {
  constructor(vm) {
    this.vm = vm
  }
  
  vmx() {
    return this.vm.x
  }
}

const vm = new Vue({
  el: '#app',
  data() {
    return {
      x: 2,
      y: new Test(this),
    }
  }
})
<script src="https://unpkg.com/vue@2.6.11/dist/vue.min.js"></script>

<div id="app">
  <p>{{ y.vmx() }}</p>
</div>

Related