title: Vue.js - Parent <-> Slot Communication
body: <p>I'm writing a small collection of Vue components to create a library to use in future projects, but I'm quite confused about this topic; maybe I need a completely different approach, but I don't know...</p>
  <p>I'm taking inspiration from (I think that's how is called) the policy pattern: you create a template component whose behaviour depends on nested components you pass as argouments. For example I created a Preview component which owns a method to change the bkg image and I want to nest in this component an overlay with the ability to call this method. Since this overlay can be everything I thought it would be nice if it has been nested through a slot:</p>
  <pre><code>&lt;template&gt;
    &lt;div class=&quot;preview&quot; :class=&quot;{active: active}&quot;&gt;
      &lt;div class=&quot;content&quot;&gt;
        &lt;slot name=&quot;content&quot;&gt;&lt;/slot&gt;
      &lt;/div&gt;
      &lt;div class=&quot;overlay&quot;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/div&gt;
      &lt;/div&gt;
  &lt;/template&gt;
  </code></pre>
  <p>(I'll make the content a v-for through a img list)</p>
  <p>And the js:</p>
  <pre><code>props: {
      content: {default: function () { return [] }}
    },
    data: function () {
      return {
        preview: null
      }
    },
    methods: {
      setPreview: function (e) {
        this.preview = e
      }
    }
  }
  </code></pre>
  <p>Then there's the child component which triggers the change onmouseover:</p>
  <pre><code>&lt;template&gt;
    &lt;div @mouseover=&quot;set&quot;&gt;
      &lt;slot&gt;&lt;/slot&gt; &lt;!-- some random content --&gt;
    &lt;/div&gt;
  &lt;/template&gt;
  
  &lt;script&gt;
  export default {
    props: ['target']
    methods: {
      set: function () {
        // figure a way to call &quot;parent&quot; setPreview
      }
    }
  }
  &lt;/script&gt;
  </code></pre>
  <p>And then I would use this component like this:</p>
  <pre><code>&lt;preview&gt;
    &lt;template slot=&quot;content&quot;&gt;... a bounch of v-if bound images&lt;/template&gt;
    &lt;template&gt;
      &lt;change-preview-onover target=&quot;first-img&quot;&gt;...&lt;/change-preview-onover&gt;
      &lt;change-preview-onclick target=&quot;second-img&quot;&gt;...&lt;/change-preview-onclick&gt; &lt;!-- different policy --&gt;
    &lt;/template&gt;
  &lt;/preview&gt;
  </code></pre>
  <p>I've tried two different approaches: scoped slots and provide/inject.
  With scoped slots I get something like this:</p>
  <pre><code>//preview
  &lt;template&gt;
    &lt;div class=&quot;preview&quot; :class=&quot;{active: active}&quot;&gt;
      &lt;div class=&quot;content&quot;&gt;
        &lt;slot name=&quot;content&quot;&gt;&lt;/slot&gt;
      &lt;/div&gt;
      &lt;div class=&quot;overlay&quot; :callback=&quot;{setPreview}&quot;&gt;&lt;slot&gt;&lt;/slot&gt;&lt;/div&gt;
      &lt;/div&gt;
  &lt;/template&gt;
  //js...
  
  //overlay element
  &lt;template&gt;
    &lt;div @mouseover=&quot;set&quot;&gt;
      &lt;slot&gt;&lt;/slot&gt; &lt;!-- some random content --&gt;
    &lt;/div&gt;
  &lt;/template&gt;
  &lt;script&gt;
  export default {
    props: ['target', 'callback']
    methods: {
      set: function () {
        this.callback.setPreview(this.target)
      }
    }
  }
  &lt;/script&gt;
  
  //usage
  &lt;preview&gt;
    &lt;template slot=&quot;content&quot;&gt;... a bounch of v-if bound images&lt;/template&gt;
    &lt;template slot-scope={callback}&gt;
      &lt;change-preview-onover :callback=&quot;callback&quot; target=&quot;first-img&quot;&gt;...&lt;/change-preview-onover&gt;
      &lt;change-preview-onclick :callback=&quot;callback&quot; target=&quot;second-img&quot;&gt;...&lt;/change-preview-onclick&gt;
    &lt;/template&gt;
  &lt;/preview&gt;
  </code></pre>
  <p>I don't like this way because it breaks encapsulation (the user must know the existence of callback and pass it through all the change-previews components) and got a lot of redundant code. I've tried to move the slot-scope inside the overlay component but without any luck.
  So I've read about provide/inject and basically now I do like this:</p>
  <pre><code>//preview.js
  provide: function () {
    return {
      setPreview: this.setPreview
    }
  }
  
  //overlay.js
  inject: ['setPreview'],
  props: ['target'],
  methods: {
    set: function () {
      this.setPreview(this.target)
    }
  }
  </code></pre>
  <p>This look pretty cool but I've not understand if that's the way provide/inject is meant to be used, or if it's ok to use it everywhere (mainly performance wise, I'll literally abuse it) to create a parent &lt;-&gt; slot communication, where, of course, slot is something semantically linked to the parent</p>
  <p><strong>EDIT 1</strong></p>
  <p>In Vue.js there's a standard way to handle parent child communication:</p>
  <p><a href="https://i.stack.imgur.com/8KsBf.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/8KsBf.png" alt="parent/child" /></a></p>
  <p>But this doesn't work whit slot because of how Vue handles the scope of components. Given my example Preview is not the parent of overlay since it's not directly nested inside the component template. Instead if I write something like this:</p>
  <pre><code>&lt;template&gt;
    &lt;div class=&quot;preview&quot; :class=&quot;{active: active}&quot;&gt;
      &lt;content&gt;...&lt;content&gt; &lt;!-- changes here --&gt;
      &lt;overlay&gt;...&lt;/overlay&gt; &lt;!-- and here --&gt;
    &lt;/div&gt;
  &lt;/template&gt;
  </code></pre>
  <p>Overlay and Content are free to communicate with Preview simply emitting events.
  But throught slot, like in the first example I proposed before, content and overlay (and preview) are all children of a generic App content, and so emit doesn't fire to Preview, but to App (or whatever contains the preview component); so I need a new way to communicate from slot to parent and vice versa.</p>
  <p>The main thread about this subject: <a href="https://github.com/vuejs/vue/issues/4332" rel="nofollow noreferrer">https://github.com/vuejs/vue/issues/4332</a>
  Here they use scoped slot (ok, but awful) or $parent, which I can't use because it needs that slot is a direct children of the parent which is not always true, maybe I want to add a transition or something else, getting something like this:</p>
  <pre><code>//Modal
  &lt;div&gt;
    &lt;tr-fade&gt; &lt;!-- tr-fade is a registered comopnent and so it's the $parent of slot --&gt;
      &lt;slot&gt;&lt;/slot&gt;
    &lt;/tr-fade&gt;
  &lt;/div&gt;
  </code></pre>
  <p><strong>My question is:</strong>
  Is the <a href="https://v2.vuejs.org/v2/api/#provide-inject" rel="nofollow noreferrer">provide/inject</a> a good way to handle this cases? Does slot-scope suit better, even if imho breaks encapsulation and it's verbose? Or there are other ways to achieve this &quot;policy pattern&quot; without giving up the level of customization the slot offers?</p>