We have a component in Vue which is a frame, scaled to the window size, which contains (in a <slot>
) an element (typically <img>
or <canvas>
) which it scales to fit the frame and enables pan and zoom on that element.
The component needs to react when the element changes. The only way we can see to do it is for the parent to prod the component when that happens, however it would be much nicer if the component could automatically detect when the <slot>
element changes and react accordingly. Is there a way to do this?
I would suggest you to consider this trick: https://codesandbox.io/s/1yn7nn72rl, that I used to watch changes and do anything with slot content.
The idea, inspired by how works VIcon component of vuetify, is to use a functional component in which we implement logic in its
render
function. Acontext
object is passed as the second argument of therender
function. In particular, thecontext
object has adata
property (in which you can find attributes,attrs
), and achildren
property, corresponding to the slot (you could event call thecontext.slot()
function with the same result).Best regards
To my knowledge, Vue does not provide a way to do this. However here are two approaches worth considering.
Watching the Slot's DOM for Changes
Use a MutationObserver to detect when the DOM in the
<slot>
changes. This requires no communication between components. Simply set up the observer during themounted
callback of your component.Here's a snippet showing this approach in action:
Using Emit
If a Vue component is responsible for changing the slot, then it is best to emit an event when that change occurs. This allows any other component to respond to the emitted event if needed.
To do this, use an empty Vue instance as a global event bus. Any component can emit/listen to events on the event bus. In your case, the parent component could emit an "updated-content" event, and the child component could react to it.
Here is a simple example: