簡體   English   中英

如何從更改組件中的值的 Svelte 組件導出 function?

[英]How can I export a function from a Svelte component that changes a value in the component?

我有一個名為WastedTime.svelte的組件,其值為wastedTime 還有一個 function 將值更改為50 (在我的實際代碼中,這是一個 animation 但這是堆棧溢出的簡化測試用例)。

為了允許從父級調用子 function,我在 Svelte 文檔中使用了<script context="module">

<script context="module">
    var wastedTime = 0;
    export function changeNumber(){
        console.log('changing number')
        wastedTime = 50
    }
</script>

<script>
    // Putting 'var wastedTime = 0' here doesn't work either
</script>


<h1>Wasted time: {wastedTime}</h1>

父級從 onMount 調用子級中的onMount

<script>

    import { onMount } from 'svelte';
    import WastedTime, {changeNumber } from './WastedTime.svelte';

    onMount(() => {
        changeNumber()
    });
</script>

<WastedTime />

問題是,由於在<script context="module">中引用了wastedTime ,它似乎無法更改wastedTime 導出的 function 運行,但wastedTime保持為 0。

在 Svelte REPL 上的副本

我嘗試過: - 將var wastedTime = 0放入<script context="module"> - 將var wastedTime = 0放入<script>

兩者都不起作用。

如何從更改組件中的值的 Svelte 組件導出 function?

<script context="module">不是響應式的——更改此塊內的變量不會影響單個實例(除非您更改了存儲值,並且每個實例都訂閱了該存儲)。

相反,直接從實例中導出changeNumber function,並使用bind:this獲取對它的引用:

浪費時間.svelte

<script>
    var someNumber = 0;
    export function changeNumber(){
        console.log('changing number')
        someNumber = 56
    }
</script>

<h1>Wasted time: {someNumber}</h1>

App.svelte

<script>
    import { onMount } from 'svelte';
    import WastedTime from './WastedTime.svelte';

    let wastedTimeComponent;

    onMount(() => {
        wastedTimeComponent.changeNumber()
    });
</script>

<WastedTime bind:this={wastedTimeComponent} />

此處演示: https://svelte.dev/repl/f5304fef5c6e43edb8bf0d25d634f965

豐富的答案的簡化版本:

App.svelte

<script>
import Time from './Time.svelte';

let timeComponent;
let time;
</script>

<Time bind:this={timeComponent} bind:time />

<h1>Spent time: {time} ms</h1>

{#if timeComponent}
  <button on:click={() => timeComponent.spendTime() }>Click me</button>
{:else}
  Loading...
{/if}

時間.svelte

<script>
export var time = 0;
export function spendTime() {
  time += 50;
}
</script>

這里的關鍵是export function

嗯,這是一個該死的好問題!

我的第一次嘗試:

我已經嘗試過@Rich Harris 的答案(從組件中導出 function,在使用帶有onMount事件偵聽器的組件時綁定它)。 這個概念確實很可靠,但我的問題有點復雜——我試圖傳遞一個帶有參數的事件,以便從外部調用。 是的 - 這個參數是使用{#await}偽造的......所以......這種方法不走運


我的第二次嘗試:

在了解了有關 svelte 如何處理事件的更多信息(我是 svelte 的新手並隨着我的進步而學習)之后,我發現了這篇很棒的文章。 簡而言之:讓我們的組件真正面向事件! 在你的問題中 - 你實際上試圖實現onload事件......所以......為什么我們不應該這樣做?

組件.svelte

<script>
  import { createEventDispatcher, onMount } from 'svelte';
  const dispatch = createEventDispatcher();

  function doSomething() { console.log('wowza!') }
  
  // wait for onMount to trigger, then dispatch event named "load"
  onMount(() => dispatch('load', 
  { 
    data: 'yay',
    doSomething
  }));
</script>

應用程序.svelte

<script>
  import { Component } from './component.svelte';

  function component_load(event)
  {
    console.log(event.detail.data);
    event.detail.doSomething();
  }
</script>
<Component on:load={component_load} />

所以 - 是的,我今天學到了一些東西:另外:

  • 這是一種更優雅的編碼方式(事件驅動)
  • 組件通過正確使用 Svelte 事件生命周期來暴露自己
  • dispatch可以被觸發以響應其他事件——讓你為你的組件構建一個完整的生命周期

驚人!

更簡單的解決方案

父組件:

<script>
    import Counter from './Counter.svelte'
    let counterElement
</script>

<Counter bind:this={counterElement} />

<button on:click={_=> counterElement.add()}>Add</button>

子組件:

<script>
    export const add =_=> count += 1
    let count = 0
</script>

<div>Count: {count}</div>

一探究竟:

https://svelte.dev/repl/70cff59aee444dd3ab772a244bd8fa36?version=3.48.0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM