在 Svelte 中将 Parent 方法传递给 Child

Passing Parent Method to Child in Svelte

如标题所示,我正在尝试将方法从 parent 组件传递到 child 组件。

例如,

App.html

<div>
  <TodoItem
     done={todo.done}
     toggle={toggle}
  />
</div>
<script>
 import TodoItem from './TodoItem.html';
 export default {
   components: {
     TodoItem,
   },
   methods: {
     toggle(index) {
       console.log(index);
     },
   },
 };
</script>

TodoItem.html

<div>
  <button on:click="toggle(0)"></button>
</div>
<script>
 export default {
   methods: {
     toggle(index) {
       // a guess. this works if you pass in console.log
       this.options.data.toggle(index)
     },
   },
 };
</script>

所需的功能是 TodoItem 使用其数据调用 parent 的方法。

此示例中断,控制台记录 TypeError: this.options.data.toggle is not a function

可以将方法传递给子组件,但这有点尴尬。更惯用的方法是从子组件触发一个事件并从父组件监听该事件:

App.html

<div>
  <TodoItem
    {todo}
    on:toggle="toggle(todo)"
  />
</div>
<script>
  import TodoItem from './TodoItem.html';
  export default {
    components: {
      TodoItem,
    },
    methods: {
      toggle(todo) {
        todo.done = !todo.done;
        const { todos } = this.get();
        this.set({ todos });
     }
   }
 };
</script>

TodoItem.html

<div>
  <button on:click="fire('toggle')">{todo.description}</button>
</div>

如果您需要通过多个级别的组件向上传递事件,您可以重新触发该事件...

<TodoItem on:toggle="fire('toggle', event)">...</TodoItem>

...但是有一个 shorthand 这样做意味着同样的事情:

<TodoItem on:toggle>...</TodoItem>

似乎“fire”是 svelte v2 的一部分,但在 svelte v3 中它被更改为 createEventDispatcher

例如-

child.svelte

<script>
    import { createEventDispatcher } from 'svelte';

    const dispatch = createEventDispatcher();

    function sayHello() {
        dispatch('message', {
            text: 'Hello!'
        });
    }
</script>

<button on:click={sayHello}>
    Click to say hello
</button>

parent.svelte

<script>
    import Inner from './child.svelte';

    function handleMessage(event) {
        alert(event.detail.text);
    }
</script>

<Inner on:message={handleMessage}/>

了解更多信息 - 请访问:https://svelte.dev/tutorial/component-events

这对我有用。

来自SOURCE

Useful when the component can't live without a parent, and the parent can't live without the component

App.svelte

<script>
    import Child from './Child.svelte'
    
    const handleSubmit = value => {
        console.log(value)
    }
</script>

<Child {handleSubmit}/>

Child.svelte

<script>
    export let handleSubmit
    let value = ''
    
    const onSubmit = e => {
        e.preventDefault()
        handleSubmit(value)
    }
</script>

<form on:submit={onSubmit}>
    <input type="text" bind:value/>
</form>

另一个解决方案是使用上下文

Useful when all the children and grandchildren components may or may not call the function. The function allows all children and grandchildren components to update the state / make changes to the common parent component.

REPL

App.svelte

<script>
    import { getContext, setContext } from 'svelte';
    import Child1 from './Child1.svelte';
    import Child2 from './Child2.svelte';
    
    let counter = 10;
    
    setContext('counter', { increment, decrement });
    
    function increment(delta) {
        counter += delta;
    }
    function decrement(delta) {
        counter -= delta;
    }
</script>

<Child1 />
<Child2 />

<button on:click={() => { increment(10); }}>
    Increment x10
</button>

<div>{counter}</div>

Child1.svelte

<script>
    import { getContext } from 'svelte';
    
    const { increment } = getContext('counter');
</script>

<button on:click={() => increment(1)}>Increment</button>

Child2.svelte

<script>
    import { getContext } from 'svelte';
    
    const { decrement } = getContext('counter');
</script>

<button on:click={() => decrement(1)}>Decrement</button>