问题
I'm new to Svelte. I have 2 Svelte components in an HTML parent-child relationship – as opposed to a Svelte P/C relationship (where 1 Svelte component imports another).
Ultimately, I want something like this (could have many Accs.):
<Accordion header={--property from SvelteComponent-- }>
<SvelteComponent />
</Accordion>
I would like the SvelteComponent to define the header used in the Accordion (it can be dynamic). I can use stores for this but that seems too messy. Accordion does contain a slot but I can’t see how to pass information upward. Can anyone suggest a path forward?
回答1:
One option is to use component bindings. This allows a two-way binding between a value in the scope of a container component and a prop of the contained component.
<Accordion {header}>
<SvelteComponent bind:header={header} />
</Accordion>
and in SvelteComponent.svelte:
<script>
export let header = "defaultHeader";
</script>
Whenever SvelteComponent makes a change to defaultHeader, it will propogate back up via the binding to the file which contains the Accordion and SvelteComponent, and apply the changes back downward. https://svelte.dev/tutorial/component-bindings
Alternatively, you can provide a setHeader
function as a prop to SvelteComponent, which sets the value of header:
//SvelteComponent.svelte
<script>
export let setHeader;
</script>
<div on:click={() => setHeader("myHeader")}>
My Svelte Component
</div>
回答2:
Svelte is great at getting rid of boilerplate and unnecessary extra code. I want to take that as far as I can.
I believe using @skeletizzle answer that I would have to add a variable to the container of the Accordions, for each Accordion and its child. THAT is what I want to eliminate (it pollutes the namespace of the container for a trivial operation). Since the Accordion and its child are in a P/C relation - they know about each other and the compiler could make communication direct. Think of an implied interface where the Accordion looks in its child and it it finds a prop named, say 'header', automatically, reactively, uses that for its own header prop.
What I am going to do is use stores though as stated, I feel they are too heavy - but don't think I have an alternative.
WrappedComponent.svelte
<script context="module">
import { writable } from 'svelte/store'
export let thisComponentHeader = writable('default header')
</script>
App.svelte
import WrappedComponent, { thisComponentHeader } from './WrappedComponent.svelte'
...
<Accord header={$thisComponentHeader}>
<WrappedComponent />
</Accord>
There still is a variable. but it is socked away in the import definition
One thing this prevents is having more than 1 instance of the component.
来源:https://stackoverflow.com/questions/61960147/how-to-pass-data-from-child-to-parent-with-2-svelte-components-in-html-parent-ch