使用从父组件传递的值初始化 prop,但稍后映射到存储中的反应变量/值

Yan*_*ans 1 svelte svelte-3 sveltekit

在 Parent.svelte 中:

<Child {initialName}/>
Run Code Online (Sandbox Code Playgroud)

在Child.svelte中

export let initialName;
<p>{initialName}</p>
Run Code Online (Sandbox Code Playgroud)

这工作正常,initialName 是根据从 Parent 传递的值呈现的。但我想稍后将其映射到存储中的反应变量(一旦呈现初始合成)。

import {_name} from './store.js';

$: initialName = $_name;
Run Code Online (Sandbox Code Playgroud)

不起作用,因为初始名称将立即被存储中的值覆盖。目前我正在执行以下解决方法。

let initialized = false;
let l_name;
$: if (true || $_name) {
    if (initialized) {
        l_name = $_name;
    } else {
        l_name = initialName;
        initialized = true;
    }
}

<p>{l_name}</p>
Run Code Online (Sandbox Code Playgroud)

这可行,但我发现它有点老套,而且样板太多。还有其他干净的方法来完成同样的任务吗?一种选择是直接设置值来存储(在父组件中)并使用它<p>$_name</p>。但是,当我刷新页面一瞬间时,这会导致保留存储中的旧值的问题。

hac*_*ape 5

您只需设置 2 个单独的反应语句:

$: name = $_name;        // `$_name` mutation will write to `name`
$: name = initialName;   // `initialName` will override `name`, if it also mutates
Run Code Online (Sandbox Code Playgroud)

或者,如果您只想initialName在第一次安装时覆盖,而不是在后续更新时覆盖,请使用onMount(callback)而不是反应式语句:

$: name = $_name;       // `$_name` mutation is always sync'ed to `name`
onMount(() => {
    name = initialName; // but `initialName` only writes once on mount
})
Run Code Online (Sandbox Code Playgroud)

示例代码,你自己看看。

<!-- Child.svelte -->

<script context="module">
    import { writable, derived } from 'svelte/store'
    export const _name = writable("zoo")
</script>

<script>    
    export let initialName;
    $: name = $_name;  
    $: name = initialName;
</script>

<p>{name}</p>
Run Code Online (Sandbox Code Playgroud)
<!-- Parent.svelte -->

<script>
    import Child, { _name } from './Child.svelte'
    let initialName = "foobar"
</script>

<Child {initialName} />

<label>initialName: <input bind:value={initialName} /></label>
<label>store value: <input bind:value={$_name} /></label>
Run Code Online (Sandbox Code Playgroud)