在 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.
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>
如标题所示,我正在尝试将方法从 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.
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>