监听来自 Svelte 组件的调度事件
Listening to a dispatched event from a Svelte component
我正在寻找一种方法来监听来自 JavaScript(而不是来自 on:
语法)的另一个组件中的 Svelte 组件的调度事件。
Here 是我试图在 REPL 上实现的代码。
预期的行为是在单击 Close 0 按钮时在控制台中显示 0,依此类推其他的。
我对 svelte 的编译代码进行了一些挖掘,找到了一个解决方案来监听 svelte 的已处理事件,但它并不漂亮:)
您可以(并且应该)在调用 onClose
时调度您自己的自定义事件,但这是解决方案:
在 Nested.svelte
<script context="module">
let counter = 0
</script>
<script>
import { createEventDispatcher, onMount } from 'svelte';
// add this
import { get_current_component } from 'svelte/internal';
let _this;
const id = counter++
const dispatch = createEventDispatcher()
/*********
and add this reactive statement
**********/
$: {
if (_this){
_this.parentNode.hosts = (_this.parentNode.hosts || []);
_this.parentNode.hosts.push(get_current_component());
}
}
/*********
end
**********/
function onClose() {
dispatch('close', id)
}
</script>
<!-- bind this -->
<button bind:this={_this} class='nested-button' on:click={onClose}>
Close {id}
</button>
然后在你的App.svelte
<script>
import { onMount } from 'svelte'
import Nested from './Nested.svelte'
let element
onMount(() => {
// requestAnimationFrame is required!
requestAnimationFrame(() => element.hosts.forEach(nestedButton => {
nestedButton.$on('close', (e) => {
console.log(e.detail)
})
}));
})
</script>
<ul bind:this={element}>
<Nested/>
<Nested />
<Nested />
</ul>
解释 -
绑定到 svelte 事件的唯一方法是获取调用组件的引用并调用 $on
方法,但目前没有简单的方法来获取组件的引用。
所以我所做的是调用 svelte 的内部 get_current_component
,这将 return 当前组件(但由于某些原因在 onMount
内部调用时不起作用)。
我将引用附加到组件中最顶层元素的 parentNode.hosts
,在本例中是 ul
元素。
然后您可以为 element.hosts
中的每个引用调用 $on
方法。
然而,适当的解决方案将像这样调度您自己的事件:
function onClose() {
dispatch('close', id)
this.dispatchEvent(new CustomEvent('close', {detail: id}));
}
通过这种方式,在不影响 svelte 内部结构的情况下实现了几乎完全相同的事情
我使用 svelte 存储和反应性:
signals.js:
import { writable } from 'svelte/store';
export const endSignal = writable({});
Sender.svelte:
<script>
import { endSignal } from './signals.js';
const signal = $endSignal;
function handleEndSignal(){
// do other stuff, then send signal
endSignal.update(()=> signal);
}
</script>
<button on:click={handleEndSignal}>The End</button>
Receiver.svelte:
<script>
import { endSignal } from './signals.js';
$: endItAll(), $endSignal;
let countEnds = 0;
function endItAll(){
countEnds +=1;
}
</script>
<p>times end signal received: {countEnds}</p>
基本上,每次我们单击 Sender.svelte 中的按钮时,“signals.js”中的值“endSignal”都会被覆盖,因此在 Receiver.svelte 中,“$”中的更新变量:" 语句触发函数 "endItAll()"。
我正在寻找一种方法来监听来自 JavaScript(而不是来自 on:
语法)的另一个组件中的 Svelte 组件的调度事件。
Here 是我试图在 REPL 上实现的代码。
预期的行为是在单击 Close 0 按钮时在控制台中显示 0,依此类推其他的。
我对 svelte 的编译代码进行了一些挖掘,找到了一个解决方案来监听 svelte 的已处理事件,但它并不漂亮:)
您可以(并且应该)在调用 onClose
时调度您自己的自定义事件,但这是解决方案:
在 Nested.svelte
<script context="module">
let counter = 0
</script>
<script>
import { createEventDispatcher, onMount } from 'svelte';
// add this
import { get_current_component } from 'svelte/internal';
let _this;
const id = counter++
const dispatch = createEventDispatcher()
/*********
and add this reactive statement
**********/
$: {
if (_this){
_this.parentNode.hosts = (_this.parentNode.hosts || []);
_this.parentNode.hosts.push(get_current_component());
}
}
/*********
end
**********/
function onClose() {
dispatch('close', id)
}
</script>
<!-- bind this -->
<button bind:this={_this} class='nested-button' on:click={onClose}>
Close {id}
</button>
然后在你的App.svelte
<script>
import { onMount } from 'svelte'
import Nested from './Nested.svelte'
let element
onMount(() => {
// requestAnimationFrame is required!
requestAnimationFrame(() => element.hosts.forEach(nestedButton => {
nestedButton.$on('close', (e) => {
console.log(e.detail)
})
}));
})
</script>
<ul bind:this={element}>
<Nested/>
<Nested />
<Nested />
</ul>
解释 -
绑定到 svelte 事件的唯一方法是获取调用组件的引用并调用 $on
方法,但目前没有简单的方法来获取组件的引用。
所以我所做的是调用 svelte 的内部 get_current_component
,这将 return 当前组件(但由于某些原因在 onMount
内部调用时不起作用)。
我将引用附加到组件中最顶层元素的 parentNode.hosts
,在本例中是 ul
元素。
然后您可以为 element.hosts
中的每个引用调用 $on
方法。
然而,适当的解决方案将像这样调度您自己的事件:
function onClose() {
dispatch('close', id)
this.dispatchEvent(new CustomEvent('close', {detail: id}));
}
通过这种方式,在不影响 svelte 内部结构的情况下实现了几乎完全相同的事情
我使用 svelte 存储和反应性:
signals.js:
import { writable } from 'svelte/store';
export const endSignal = writable({});
Sender.svelte:
<script>
import { endSignal } from './signals.js';
const signal = $endSignal;
function handleEndSignal(){
// do other stuff, then send signal
endSignal.update(()=> signal);
}
</script>
<button on:click={handleEndSignal}>The End</button>
Receiver.svelte:
<script>
import { endSignal } from './signals.js';
$: endItAll(), $endSignal;
let countEnds = 0;
function endItAll(){
countEnds +=1;
}
</script>
<p>times end signal received: {countEnds}</p>
基本上,每次我们单击 Sender.svelte 中的按钮时,“signals.js”中的值“endSignal”都会被覆盖,因此在 Receiver.svelte 中,“$”中的更新变量:" 语句触发函数 "endItAll()"。