[Svelte] Props
The data passed from parents to children is called properties (props).
Example
At first, let's create a child component.
<!-- components/User.svelte -->
<script lang="ts">
export let name;
export let age = 20;
</script>
<div>
<h1>{name}, {age}</h1>
</div>
This component gets data named as name, age from the parent component and display it.
If age data aren't passed, this component will use the default value.
Now, let's use this component in the parent.
<script lang="ts">
import User from '../components/User.svelte';
let users = [
{ name: 'HoYa', age: 18 },
{ name: 'Park', age: 17 },
{ name: 'Lee' }
];
</script>
<div>
{#each users as user}
<User name={user.name} age={user.age} />
{/each}
<!-- or -->
{#each users as { name, age }}
<User {name} {age} />
{/each}
<!-- or -->
{#each users as user}
<User {...user} />
{/each}
</div>
We can pass the data in several ways like the above example.
Binding Props
Props is basically unidirectional. But, if we use binding, it can be bidirectional.
<!-- componentes/ToDo.svelte -->
<script lang="ts">
export let todos;
export let index;
export let todo;
function deleteToDo() {
todos.splice(index, 1);
todos = todos;
}
</script>
<div>
<input type="checkbox" bind:checked={todo.done} />
{todo.content}
<button on:click={deleteToDo}>X</button>
</div>
When I update the to-do list, I want to apply the changed list to a parent component.
If I use props In this case, it cannot apply to the parent.
Then, how should I do about this?
<script lang="ts">
import ToDo from '../components/ToDo.svelte';
let todos = [
{ id: 1, content: '1st thing', done: false },
{ id: 2, content: '2nd thing', done: true }
];
</script>
{#each todos as todo, index (todo.id)}
<ToDo bind:todos {index} {todo} />
{/each}
Use bind: if we want bidirectional reactivity.
$$props and $$restProps
$$props and $$restProps are built-in objects of Svelte.
$$props has all the props passed and $$restProps has all the props except for the explicitly defined props.
<!-- components/Props.svelte -->
<script lang="ts">
export let color;
</script>
<div>
<input style="color:{color};" {...$$props} />
<!-- or -->
<input style="color:{color};" {...$$restProps} />
</div>
In other words, $$props has color props and $$restProps doesn't have color props.
<script lang="ts">
import Props from '../components/Props.svelte';
</script>
<Props type="email" placeholder="Please input your email" color="tomato" required />
<Props type="password" maxlength="14" color="teal" required />
These built-in objects can be used to pass props without caring.
--style-props
We can pass user-defined CSS properties as well.
<!-- components/StyleProps.svelte -->
<div>Test</div>
<style>
:global(html) {
--width: 50px;
--height: 50px;
--primary-color: white;
--secondary-color: black;
}
div {
width: var(--width);
height: var(--height);
color: var(--primary-color);
background-color: var(--secondary-color);
}
</style>
<script lang="ts">
import StyleProps from '../components/StyleProps.svelte';
</script>
<StyleProps />
<StyleProps --width="100px" --height="100px" --primary-color="teal" --secondary-color="tomato" />
It's easy to use.
But, some old browsers cannot support this because --style-props uses "display: contents".