如何在 svelte 中从另一个 child 更新 child 组件
How to update a child component from another child in svelte
我在汽车名称上有一个 select 显示汽车颜色。当我在 car 字段中输入汽车并且它存在于汽车列表中时,我在 Maintain 中显示颜色(这有效)
如果我改变当前select车上的颜色并保存更改,我希望更新后的颜色出现在原理child的输入框中(汽车)
如果我 re-select 汽车,它可以工作,但我希望它在单击 保存 按钮后立即更新。
如何在保存时更新颜色?
这是REPL
App.svelte
<script>
import Cars from './Cars.svelte'
import MaintainCar from './MaintainCar.svelte'
let cars = {'Audi': 'red', 'BMW':'blue', 'Hillman': 'green'}
function maintenance() {
console.log(cars)
}
</script>
<main>
<Cars cars={cars}/>
<MaintainCar cars={cars} on:message={maintenance} />
</main>
Cars.svelte
<script>
export let cars
export let selected_car = ''
let colour = ''
let car_list = getCars(cars)
$: colour = cars[selected_car]
function getCars(cars) {
let car_list = []
for (const [key, value] of Object.entries(cars)) {
car_list.push(key);
}
if (!selected_car) {
selected_car = car_list[0]
colour = cars[selected_car]
}
return car_list
}
function selectCar() {
colour = cars[selected_car]
}
</script>
<select bind:value={selected_car} on:click={selectCar}>
{#each car_list as car}
<option value={car}>
{car}
</option>
{/each}
</select>
<input type="text" bind:value={colour} placeholder="colour"/>
MaintainCar.svelte
<div>
<input type="text" bind:value={car} placeholder="car"/>
<input type="text" bind:value={colour} placeholder="colour"/>
<div>
<button class="select-button" on:click={saveData}>Save</button>
</div>
</div>
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
export let cars
let car = ''
$: colour = checkCar(car)
function checkCar(car) {
colour = '';
if (car && car in cars) {
colour = cars[car];
}
return colour
}
function saveData() {
cars[car] = colour;
car = ''
colour = ''
dispatch('message', {
text: 'colour'
});
}
</script>
好吧,如果您希望信息以一种方式下降,并以另一种方式返回,您需要... two-way 绑定!
变化:
<MaintainCar cars={cars} on:message={maintenance} />
至:
<MaintainCar bind:cars={cars} on:message={maintenance} />
现在它附带了很多的注意事项...
首先,它仅在 child 组件中分配给从外部绑定的完全相同的变量时才有效。就像您现在碰巧做的那样,但是很容易丢失它,因为您从数组中提取一个项目,从 object 中提取一个道具或其他任何东西。总而言之,您必须小心 在 child 组件 中所做的事情,以支持从外部使用它的方式[=40] =],这种情况很少见。
第二个警告是关于 two-way 一般绑定。虽然它在某些情况下非常有用并且可以节省大量样板文件,但它也可能导致建立一个难以跟踪依赖关系的混乱网络,上下波动......因此,请谨慎使用。
一个通常更合理的方法是使用一个商店,它本身具有反应性,而不是依赖于脆弱和棘手的 two-way 绑定链。 Svelte 让这一切变得简单!
您可以更改 parent 组件中的 cars
反应变量:
<script>
const cars = writable({'Audi': 'red', 'BMW':'blue', 'Hillman': 'green'})
// don't forget to prefix it with $ to access its _value_
console.log($cars)
...
</script>
<!-- pass the store directly to children (not the value) -->
<Cars {cars}/>
<MaintainCar {cars} on:message={maintenance} />
然后 children 可以轻松地访问存储中的值或更改它,并将更改传播回使用该存储的任何地方:
<script>
export let cars
function saveData() {
$cars[car] = colour;
}
...
</script>
...
请参阅此 REPL 并将您的示例转换为商店。
我在汽车名称上有一个 select 显示汽车颜色。当我在 car 字段中输入汽车并且它存在于汽车列表中时,我在 Maintain 中显示颜色(这有效)
如果我改变当前select车上的颜色并保存更改,我希望更新后的颜色出现在原理child的输入框中(汽车)
如果我 re-select 汽车,它可以工作,但我希望它在单击 保存 按钮后立即更新。
如何在保存时更新颜色?
这是REPL
App.svelte
<script>
import Cars from './Cars.svelte'
import MaintainCar from './MaintainCar.svelte'
let cars = {'Audi': 'red', 'BMW':'blue', 'Hillman': 'green'}
function maintenance() {
console.log(cars)
}
</script>
<main>
<Cars cars={cars}/>
<MaintainCar cars={cars} on:message={maintenance} />
</main>
Cars.svelte
<script>
export let cars
export let selected_car = ''
let colour = ''
let car_list = getCars(cars)
$: colour = cars[selected_car]
function getCars(cars) {
let car_list = []
for (const [key, value] of Object.entries(cars)) {
car_list.push(key);
}
if (!selected_car) {
selected_car = car_list[0]
colour = cars[selected_car]
}
return car_list
}
function selectCar() {
colour = cars[selected_car]
}
</script>
<select bind:value={selected_car} on:click={selectCar}>
{#each car_list as car}
<option value={car}>
{car}
</option>
{/each}
</select>
<input type="text" bind:value={colour} placeholder="colour"/>
MaintainCar.svelte
<div>
<input type="text" bind:value={car} placeholder="car"/>
<input type="text" bind:value={colour} placeholder="colour"/>
<div>
<button class="select-button" on:click={saveData}>Save</button>
</div>
</div>
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
export let cars
let car = ''
$: colour = checkCar(car)
function checkCar(car) {
colour = '';
if (car && car in cars) {
colour = cars[car];
}
return colour
}
function saveData() {
cars[car] = colour;
car = ''
colour = ''
dispatch('message', {
text: 'colour'
});
}
</script>
好吧,如果您希望信息以一种方式下降,并以另一种方式返回,您需要... two-way 绑定!
变化:
<MaintainCar cars={cars} on:message={maintenance} />
至:
<MaintainCar bind:cars={cars} on:message={maintenance} />
现在它附带了很多的注意事项...
首先,它仅在 child 组件中分配给从外部绑定的完全相同的变量时才有效。就像您现在碰巧做的那样,但是很容易丢失它,因为您从数组中提取一个项目,从 object 中提取一个道具或其他任何东西。总而言之,您必须小心 在 child 组件 中所做的事情,以支持从外部使用它的方式[=40] =],这种情况很少见。
第二个警告是关于 two-way 一般绑定。虽然它在某些情况下非常有用并且可以节省大量样板文件,但它也可能导致建立一个难以跟踪依赖关系的混乱网络,上下波动......因此,请谨慎使用。
一个通常更合理的方法是使用一个商店,它本身具有反应性,而不是依赖于脆弱和棘手的 two-way 绑定链。 Svelte 让这一切变得简单!
您可以更改 parent 组件中的 cars
反应变量:
<script>
const cars = writable({'Audi': 'red', 'BMW':'blue', 'Hillman': 'green'})
// don't forget to prefix it with $ to access its _value_
console.log($cars)
...
</script>
<!-- pass the store directly to children (not the value) -->
<Cars {cars}/>
<MaintainCar {cars} on:message={maintenance} />
然后 children 可以轻松地访问存储中的值或更改它,并将更改传播回使用该存储的任何地方:
<script>
export let cars
function saveData() {
$cars[car] = colour;
}
...
</script>
...
请参阅此 REPL 并将您的示例转换为商店。