JL Peyret
JL Peyret

Reputation: 12204

Can I access vue app attributes in a vue 3 method defined in the composition API?

I am having a hard time figuring out how much Vue 3 composition API methods can access the vue app's attributes, including data.

This is the jsfiddle which itself is a fork of the Vue demo fiddle.

Basically, using a method defined via the options API, I can easily retrieve data values.

However, when I use method defined via the composition API, it's pretty much as if data and the app instance in general is invisible to me. No this, as has been said before. But in general, it is as if the composition and the options API parts have been segmented apart from each other.

testopt, defined using options API, can see data, and references returned by setup.

"Yo! from options API:Hello Vue!"
"this.msg2:Hello2"

testcompo, defined in composition API can't see data, but can see references returned by setup.

"Yo! from composition API: this:undefined:"
"context:[object Object]:"
"context.data:undefined:"
"context.$data:undefined:"
"context.attrs:[object Object]:"
"context.attrs.data:undefined:"
"arg2:undefined:"
"msg2:Hello2"
"Yes, I know how setup and refs work.  counter is now:4"
<script type="importmap">
  {
    "imports": {
      "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
    }
  }
</script>

<div id="app">

<div>{{ message }}</div>

<button @click="testopt">
Test option API this
</button>

<button @click="testcompo">
Test composition API this
</button>


</div>

<script type="module">
  import { createApp, ref } from 'vue'

  createApp({
    data() {
      return {
        message: 'Hello Vue!'
      }
    },
    setup(props, context){
    
        const msg2 = ref("Hello2");
        const counter = ref(1);      
    
        function testcompo (evt, arg2) {
         console.clear();
         console.log("Yo! from composition API: this:" + this + ":");
         console.log("context:" + context + ":");
         console.log("context.data:" + context.data + ":");
         console.log("context.$data:" + context.$data + ":");
         console.log("context.attrs:" + context.attrs + ":");
         console.log("context.attrs.data:" + context.attrs.data + ":");
         console.log("arg2:" + arg2 + ":");
         console.log("msg2:" + msg2.value);
         counter.value++;
         console.log("Yes, I know how setup and refs work.  counter is now:" + counter.value);
      };
      
        return {testcompo, counter,msg2}
    },
    
    methods : {
       testopt(evt){
         console.clear();
         console.log("Yo! from options API:" + this.message)
         console.log("this.msg2:" + this.msg2);
       }
    }
  }).mount('#app')
</script>

Should I generally understand that mixing composition and options API is a no-go? Is there no interop or is there a bridge object somewhere in the context and on this allowing one side to access the other? Is there a way to get this back on composition API method?

What I have also looked at:

javascript - Vue 3 Composition API data() function - Stack Overflow

typescript - Can't access this in Vue 3 methods with regular OR arrow functions - Stack Overflow

javascript - Vue 3 composition API and access to Vue instance - Stack Overflow

But all these answers seemed more narrowly focused on explaining how to do one particular thing using composition API rather than the generic question on how composition methods interact with the Vue app instance, if at all.

Upvotes: 2

Views: 2528

Answers (1)

Nikola Pavicevic
Nikola Pavicevic

Reputation: 23500

You can use getCurrentInstance to access options api:

const { createApp, ref, getCurrentInstance } = Vue
createApp({
  data() {
    return {
      message: 'Hello Vue!'
    }
  },
  setup(props, context){
    const msg2 = ref("Hello2");    
    const vm = getCurrentInstance()
    function testcompo (evt, arg2) {
       console.clear();
       console.log("Yo! from composition API: " + msg2.value);
       console.log("message: " + vm.data.message);
    };
    return { testcompo, msg2 }
  },
  methods : {
     testopt(evt){
       console.clear();
       console.log("Yo! from options API: " + this.message)
       console.log("msg2: " + this.msg2);
     }
  }
}).mount('#app')
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="app">
  <div>{{ message }}</div>
  <button @click="testopt">
  Test option API this
  </button>
  <button @click="testcompo">
  Test composition API this
  </button>
</div>

Upvotes: 1

Related Questions