Svelte:传递已声明的函数时,反应式声明不起作用
Svelte: Reactive declaration does not work when passing a declared function
问题
我创建了一个 reactive 变量来在 state 变量发生变化时对数组进行排序。如果我直接将 sort
函数声明为回调,它确实有效,但如果我传递一个已经声明的函数则无效。
代码
所以这是不工作的代码:
const sortSongs = (a, b) => {
const [option, direction] = sortOption.split("-");
const itemA = a[option == "Song" ? "title" : "artist"].toLowerCase();
const itemB = b[option == "Song" ? "title" : "artist"].toLowerCase();
if (itemA < itemB) {
return direction == "up" ? 1 : -1;
}
if (itemA > itemB) {
return direction == "up" ? -1 : 1;
}
return 0;
};
$: filteredSongs =
lessons
?.sort(sortSongs)
.filter(lesson => lesson.title?.toLowerCase().includes(value)) || [];
这就是工作的人:
$: filteredSongs =
lessons
?.sort((a, b) => {
const [option, direction] = sortOption.split("-");
const itemA = a[option == "Song" ? "title" : "artist"].toLowerCase();
const itemB = b[option == "Song" ? "title" : "artist"].toLowerCase();
if (itemA < itemB) {
return direction == "up" ? 1 : -1;
}
if (itemA > itemB) {
return direction == "up" ? -1 : 1;
}
return 0;
})
.filter(lesson => lesson.title?.toLowerCase().includes(value)) || [];
混乱
所以不应该两者都起作用吗?为什么我声明函数的地方会有所不同?这是一个 REPL 以查看实际效果。红色的歌曲有无效代码,绿色的歌曲有有效代码。
您希望 $: filteredSongs
在 sortOption
更改时重新计算,但是当您传递函数引用 .sort(sortSongs)
时,sortOption
在函数内部是 'hidden' 并且不再与反应式陈述直接相关。 second paragraph
中的文档中提到了它
Only values which directly appear within the $: block will become dependencies of the reactive statement
一个快速而肮脏的解决方案是将 sortOption
作为参数传递
?.sort(sortSongs, sortOption)
.sort()
只期望比较函数作为参数,因此 sortOption
将被忽略,但又是一个依赖项,因为在 $:
块中再次
如果不使用 'redundant' 参数调用 .sort()
,这将是一个更清晰的替代方案
let lessons = [];
...
const sortSongs = (songs, sortOption) => {
return songs.sort((a,b) => {
const [option, direction] = sortOption.split("-");
const itemA = a[option == "Song" ? "title" : "artist"].toLowerCase();
const itemB = b[option == "Song" ? "title" : "artist"].toLowerCase();
if (itemA < itemB) {
return direction == "up" ? 1 : -1;
}
if (itemA > itemB) {
return direction == "up" ? -1 : 1;
}
return 0;
})
};
$: filteredSongs =
sortSongs(lessons, sortOption)
.filter(lesson => lesson.title?.toLowerCase().includes(value));
问题
我创建了一个 reactive 变量来在 state 变量发生变化时对数组进行排序。如果我直接将 sort
函数声明为回调,它确实有效,但如果我传递一个已经声明的函数则无效。
代码
所以这是不工作的代码:
const sortSongs = (a, b) => {
const [option, direction] = sortOption.split("-");
const itemA = a[option == "Song" ? "title" : "artist"].toLowerCase();
const itemB = b[option == "Song" ? "title" : "artist"].toLowerCase();
if (itemA < itemB) {
return direction == "up" ? 1 : -1;
}
if (itemA > itemB) {
return direction == "up" ? -1 : 1;
}
return 0;
};
$: filteredSongs =
lessons
?.sort(sortSongs)
.filter(lesson => lesson.title?.toLowerCase().includes(value)) || [];
这就是工作的人:
$: filteredSongs =
lessons
?.sort((a, b) => {
const [option, direction] = sortOption.split("-");
const itemA = a[option == "Song" ? "title" : "artist"].toLowerCase();
const itemB = b[option == "Song" ? "title" : "artist"].toLowerCase();
if (itemA < itemB) {
return direction == "up" ? 1 : -1;
}
if (itemA > itemB) {
return direction == "up" ? -1 : 1;
}
return 0;
})
.filter(lesson => lesson.title?.toLowerCase().includes(value)) || [];
混乱
所以不应该两者都起作用吗?为什么我声明函数的地方会有所不同?这是一个 REPL 以查看实际效果。红色的歌曲有无效代码,绿色的歌曲有有效代码。
您希望 $: filteredSongs
在 sortOption
更改时重新计算,但是当您传递函数引用 .sort(sortSongs)
时,sortOption
在函数内部是 'hidden' 并且不再与反应式陈述直接相关。 second paragraph
Only values which directly appear within the $: block will become dependencies of the reactive statement
一个快速而肮脏的解决方案是将 sortOption
作为参数传递
?.sort(sortSongs, sortOption)
.sort()
只期望比较函数作为参数,因此 sortOption
将被忽略,但又是一个依赖项,因为在 $:
块中再次
如果不使用 'redundant' 参数调用 .sort()
,这将是一个更清晰的替代方案
let lessons = [];
...
const sortSongs = (songs, sortOption) => {
return songs.sort((a,b) => {
const [option, direction] = sortOption.split("-");
const itemA = a[option == "Song" ? "title" : "artist"].toLowerCase();
const itemB = b[option == "Song" ? "title" : "artist"].toLowerCase();
if (itemA < itemB) {
return direction == "up" ? 1 : -1;
}
if (itemA > itemB) {
return direction == "up" ? -1 : 1;
}
return 0;
})
};
$: filteredSongs =
sortSongs(lessons, sortOption)
.filter(lesson => lesson.title?.toLowerCase().includes(value));