Home > Blockchain >  For Vue 2/3, when using provide/inject to provide a function from an ancestor component, how can tha
For Vue 2/3, when using provide/inject to provide a function from an ancestor component, how can tha

Time:04-16

I have an ancestor Vue 2 component that uses provide/inject to inject a function from the ancestor to any nested (descendant) component. However I'm finding that inside that function this is not bound to the ancestor but to the descendant.

How can I get a reference the ancestor from inside the injected function onCallback() ?

Example:

<template>
  <Intermediary />
</template>
<script>
export default {
  name: "Ancestor",
  props: ["val"],
  provide: {
    onCallback() {
      console.log(this.val); // <<< fails as `this` is bound to caller component
    }
  }
}
</script>
<template>
  <Descendant />
</template>
<script>
export default {
  name: "Intermediary"
}
</script>
<template>
  <button @click="onCallback">Click Me!</button>
</template>
<script>
export default {
  name: "Descendant",
  inject["onCallback"]
}
</script>

CodePudding user response:

You can use function syntax to access this, import computed at the top and re-write provide like:

provide() {
  return {
    onCallback: computed(() => () => console.log(this.val))
  }
}

Do note that using function syntax doesn't make injected variables reactive by default. You need to use computed to make them reactive. I highly recommend to go through this official doc to understand the concept correctly.

Working example: https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHRlbXBsYXRlPlxuICA8SW50ZXJtZWRpYXJ5IC8 XG48L3RlbXBsYXRlPlxuPHNjcmlwdD5cbiAgaW1wb3J0IEludGVybWVkaWFyeSBmcm9tIFwiLi9JbnRlcm1lZGlhcnkudnVlXCI7XG4gIGltcG9ydCB7Y29tcHV0ZWR9IGZyb20gXCJ2dWVcIlxuICBcbiAgZXhwb3J0IGRlZmF1bHQge1xuICAgIG5hbWU6IFwiQXBwXCIsXG4gICAgY29tcG9uZW50czoge1xuICAgICAgSW50ZXJtZWRpYXJ5LFxuICAgIH0sXG4gICAgZGF0YTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB2YWw6IFwiUGFyZW50XCIsXG4gICAgICB9XG4gICAgfSxcbiAgICBwcm92aWRlKCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb25DYWxsYmFjazogY29tcHV0ZWQoKCkgPT4gKCkgPT4gY29uc29sZS5sb2codGhpcy52YWwpKVxuICAgICAgfVxuICAgIH1cbiAgfVxuPC9zY3JpcHQ IiwiaW1wb3J0LW1hcC5qc29uIjoie1xuICBcImltcG9ydHNcIjoge1xuICAgIFwidnVlXCI6IFwiaHR0cHM6Ly9zZmMudnVlanMub3JnL3Z1ZS5ydW50aW1lLmVzbS1icm93c2VyLmpzXCJcbiAgfVxufSIsIkludGVybWVkaWFyeS52dWUiOiI8dGVtcGxhdGU XG4gIDxEZXNjZW5kYW50IC8 XG48L3RlbXBsYXRlPlxuPHNjcmlwdD5cbmltcG9ydCBEZXNjZW5kYW50IGZyb20gXCIuL0Rlc2NlbmRhbnQudnVlXCI7XG5leHBvcnQgZGVmYXVsdCB7XG4gIG5hbWU6IFwiSW50ZXJtZWRpYXJ5XCIsXG4gICBjb21wb25lbnRzOiB7XG4gICAgRGVzY2VuZGFudCxcbiAgfSxcbn1cbjwvc2NyaXB0PiIsIkRlc2NlbmRhbnQudnVlIjoiPHRlbXBsYXRlPlxuICA8YnV0dG9uIEBjbGljaz1cIm9uQ2FsbGJhY2tcIj5DbGljayBNZSE8L2J1dHRvbj5cbjwvdGVtcGxhdGU XG48c2NyaXB0PlxuZXhwb3J0IGRlZmF1bHQge1xuICBuYW1lOiBcIkRlc2NlbmRhbnRcIixcbiAgZGF0YTogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHZhbHg6IFwiVEVTVFwiLFxuICAgIH1cbiAgfSxcbiAgaW5qZWN0OiBbXCJvbkNhbGxiYWNrXCJdXG59XG48L3NjcmlwdD4ifQ==

CodePudding user response:

The main thing I originally missed was that provide() can be a function that is always bound to the ancestor component.

<template>
  <Intermediary />
</template>
<script>
export default {
  name: "Ancestor",
  props: ["val"],
  provide() {
    return {
      onCallback() {
        console.log(this.val); 
      }
    }
  }
}
</script>
  • Related