1
votes

I've been trying to pass down a value via a parent component to a child component without using props. I'm using provide for this on a parent component (not the highest parent). The value im passing down will be dynamically updated, so after reading the vue docs I have to do something like: Vue.computed(() => this.todos.length) but it throws an error because Vue is undefined. I seem to be unable to import Vue like this import Vue from 'vue' (or something similar). How can I make this work? To be honest, even when I try to pass down a static variable I get undefined in the (direct) child component, even when I use the exact same code as in the vue docs.
So I have 2 questions:

  1. how to refer/import the Vue instance?
  2. Is it possible to use provide on a direct parent component (which is not the root)?

I'm using Vue3

1

1 Answers

0
votes

You can get the instance using getCurrentInstance but it's not needed for what you want to do:

import { getCurrentInstance } from 'vue';
setup() {
   const internalInstance = getCurrentInstance();
}

You can provide a computed from any component. Import provide and computed in the parent and use them like:

Parent

import { provide, computed } from 'vue';
setup() {
   ...
   const total = computed(() => x.value + y.value);  // Some computed
   provide('total', total);
}

Import inject in the child:

Child

import { inject } from 'vue';
setup() {
   ...
   const total = inject('total');
}

Here's a demo (with just slightly different import syntax because the CDN doesn't use actual imports):

const { createApp, ref, computed, provide, inject } = Vue;

const app = createApp({});

// PARENT
app.component('parent', {
  template: `
  <div class="parent">
    <child></child>
    <button @click="x++">Increment</button> (from Parent)
  </div>
  `,
  setup() {
    const x = ref(5);
    const y = ref(10);
    const total = computed(() => x.value + y.value);
    provide('total', total);
    
    return {
        x
    }
  }
});

// CHILD
app.component('child', {
  template: `
  <div class="child">
    Total: {{ total }}
  </div>
  `,
  setup() {
    const total = inject('total');
    
    return {
        total
    }
  }
});

app.mount("#app");
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}
.parent, .child { padding: 24px; }
.parent {
  background: #dddddd;
}
.child {
  margin: 6px 0;
  background: #ddeeff;
}
<div id="app">
  <parent></parent>
</div>

<script src="https://unpkg.com/vue@next"></script>