admin管理员组

文章数量:1277290

I'm curious, what's the best way to forward or dispatch events across multiple levels in ponent tree in Svelte JS?

Say I have App.Svelte, some intermediate number levels, each containing a child ponent, and Modal.Svelte. If I want to forward or dispatch an event from Modal to App, what's the right way to do this?

As I understand it, event forwarding in Svelte will traverse up the ponent tree and forward the event to the first parent that references the forwarded event. (Is this the correct interpretation?)

And using event dispatch approach, each nested ponent would need to 1/ import createEventDispatcher, 2/ create a dispatcher variable, 3/ define a function, which dispatches the event. Then parent's would need to import the function and reference it inside a tag, such as <p>. (Is this correct?)

If I'm correct on both of the above, I'm wondering if there isn't a more streamlined approach, eg connecting the event to stores, which would effectively flatten the ponent tree such that any ponent could receive the forwarded event. Though I imagine that this could induce some hard to debug behavior if multiple ponents reference the same forwarded event.

I'm curious, what's the best way to forward or dispatch events across multiple levels in ponent tree in Svelte JS?

Say I have App.Svelte, some intermediate number levels, each containing a child ponent, and Modal.Svelte. If I want to forward or dispatch an event from Modal to App, what's the right way to do this?

As I understand it, event forwarding in Svelte will traverse up the ponent tree and forward the event to the first parent that references the forwarded event. (Is this the correct interpretation?)

And using event dispatch approach, each nested ponent would need to 1/ import createEventDispatcher, 2/ create a dispatcher variable, 3/ define a function, which dispatches the event. Then parent's would need to import the function and reference it inside a tag, such as <p>. (Is this correct?)

If I'm correct on both of the above, I'm wondering if there isn't a more streamlined approach, eg connecting the event to stores, which would effectively flatten the ponent tree such that any ponent could receive the forwarded event. Though I imagine that this could induce some hard to debug behavior if multiple ponents reference the same forwarded event.

Share Improve this question asked Jan 27, 2023 at 14:54 jbuddy_13jbuddy_13 1,2863 gold badges23 silver badges51 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 9

To forward a event from a child ponent or DOM element to the parent, you just have to define an on:event without handler. E.g.

<button on:click >
<Component on:open >

No need to use createEventDispatcher just for forwarding.

If you want to share events more widely, you can create an EventTarget and send events through that. Since subscriptions would not happen in the template via on:event, you have to make sure to remove listeners again. You can also use a context to just expose the object to a sub-tree of the ponent hierarchy.

Alternatively, events can be dispatched directly to DOM elements, such events will bubble up the entire element hierarchy (if enabled in the event options).

someElement.dispatchEvent(
  new CustomEvent('my-event', { bubbles: true })
);

If you dispatch events to the window, directly or via bubbling, you can subscribe to those more conveniently using svelte:window:

<svelte:window on:my-event={() => ...} />

(These handlers are removed automatically when the ponent is destroyed.)

You might consider instead using accessor functions. In App.svelte, define a function that manipulates your top-level variables. Then place that function in an accessor object and pass that down as a prop to all your ponents that may need it.

<script>
[App.svelte]

let myVar, myObj, myWhatever

function updateMyVal(newValue) {
  myVar = newValue
}

function mergeMyObject(mergeObj) {
  myObj = {...myObj, ...mergeObj}
}

let accessorObject = {
  updateMyVal: updateMyVal,
  mergeMyObject: mergeMyObject
}

</script>

<ChildComponent {accessorObject} {myVar} {myObj} />



. . .
[ChildComponent.svelte]
<script>
  export let accessorObject, myVar, myObj

  accessorObject.updateMyVal(1234)

  accessorObject.mergeMyObject({newProp: newVal})
</script>

And so forth... this has the advantage of pushing changes to application-wide variables from the top down, which I've found to work better for plex SPAs than a web of events, two-way-bindings or stores, at least in my limited experience.

本文标签: