Svelte 虚拟列表组件 - 过滤列表后功能不起作用
Svelte virtual list component - function not working after filtering list
我在一个 svelte 项目中使用 virtuallist component。我已将过滤添加到列表中。我的问题是,当我过滤列表时,我的项目中的一个函数停止工作,我假设是因为过滤时列表项尚未在 dom 中?
该项目使用两个输入将医疗单位从公制单位转换为国际单位。更改一个输入会自动转换另一个。
在过滤之前,一切都适用于转换,但在输入项目名称(例如 Type Zinc)后,输入转换在过滤的项目中失败。没有发生转换。
我已经将 afterUpdate 作为一个选项进行了研究,但不确定如何实施它。
------------添加信息 ------------------
问题出在尚未查看的列表项上。尝试键入 "zinc" 然后更改 Zinc 的输入值(失败)与键入 Acetone(已在视图中的项目)并更改这些输入(有效)。
这是一个有效的 REPL
脚本:
<script>
import VirtualList from './VirtualList.svelte';
import unitsH from './data.js';
let searchTerm = "";
let start;
let end;
$: filteredList = unitsH.filter(item => item.name.toLowerCase().indexOf(searchTerm) !== -1);
function setBothFromSIH(value, i) {
const {factor, siValue} = unitsH[i];
unitsH[i].siValue = +value;
unitsH[i].usValue = +(value / factor).toFixed(2);
}
function setBothFromUSH(value, i) {
const {factor, usValue} = unitsH[i];
unitsH[i].usValue = +value;
unitsH[i].siValue = +(value * factor).toFixed(2);
}
</script>
使用简化的 html 代码:
<VirtualList items={filteredList} bind:start bind:end let:item >
<div class="border" style="overflow-x: scroll;"> <div><div>
<div class="name">{item.name}</div>
<span>Specimen: {item.specimen} </span>
<span> Conversion Factor: {item.factor} </span>
</div>
<div>
<label>US Range:{item.conventionalRange} {item.conventionalUnit}</label>
<input name="us{filteredList.indexOf(item)}" value={item.usValue} on:input="{e => setBothFromUSH(e.target.value, filteredList.indexOf(item))}" type=number placeholder=" US">
</div>
<div>
<label>SI Range: {item.siRange} {item.siUnit}</label>
<input name="si{filteredList.indexOf(item)}" value={item.siValue} on:input="{e => setBothFromSIH(e.target.value, filteredList.indexOf(item))}" type=number placeholder="SI">
</div></div> </div>
</VirtualList>
<p>showing items {start}-{end}</p>
感谢您提供的任何帮助使它正常工作!
这是您的过滤器的一个小问题。您将产品名称转换为小写,而不是过滤条件;) 如果您输入 acetone
而不是 Acetone
,那么它会起作用。修复:
$: filteredList = unitsH.filter(item => item.name.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1);
编辑:
不为某些过滤元素调用函数的问题是您显示 filteredList
但仍然在 unitsH
列表上进行查找。把它改成这样就可以了:
function setBothFromSIH(value, i) {
const {factor, siValue} = filteredList[i];
filteredList[i].siValue = +value;
filteredList[i].usValue = +(value / factor).toFixed(2);
}
function setBothFromUSH(value, i) {
const {factor, usValue} = filteredList[i];
filteredList[i].usValue = +value;
filteredList[i].siValue = +(value * factor).toFixed(2);
}
祝您黑客愉快!
您的问题是由于使用了错误的索引引起的,在更改处理程序中您传递了 filteredIndex
中项目的索引,但随后您使用该索引更改了数组中该索引上的项目 unitsH
.
您可以通过以下方式查看:
- 重新开始
- 注意对乙酰氨基酚的值(索引 0)
- 搜索锌
- 更改锌的值(过滤列表中的索引 0)
- 清除搜索
->> 对乙酰氨基酚已更改,因为它是单位 H 中的索引 0
您可以通过传入原始数组的索引轻松解决此问题:
<input name="si{filteredList.indexOf(item)}" value={item.siValue} on:input="{e => setBothFromSIH(e.target.value, unitsH.indexOf(item))}" type=number placeholder="SI">
但是,如果您将每个项目的标记移动到一个单独的组件,您可以通过直接与属性交互而不是尝试在数组中更改它们来极大地简化它。
我在一个 svelte 项目中使用 virtuallist component。我已将过滤添加到列表中。我的问题是,当我过滤列表时,我的项目中的一个函数停止工作,我假设是因为过滤时列表项尚未在 dom 中?
该项目使用两个输入将医疗单位从公制单位转换为国际单位。更改一个输入会自动转换另一个。 在过滤之前,一切都适用于转换,但在输入项目名称(例如 Type Zinc)后,输入转换在过滤的项目中失败。没有发生转换。 我已经将 afterUpdate 作为一个选项进行了研究,但不确定如何实施它。
------------添加信息 ------------------
问题出在尚未查看的列表项上。尝试键入 "zinc" 然后更改 Zinc 的输入值(失败)与键入 Acetone(已在视图中的项目)并更改这些输入(有效)。
这是一个有效的 REPL
脚本:
<script>
import VirtualList from './VirtualList.svelte';
import unitsH from './data.js';
let searchTerm = "";
let start;
let end;
$: filteredList = unitsH.filter(item => item.name.toLowerCase().indexOf(searchTerm) !== -1);
function setBothFromSIH(value, i) {
const {factor, siValue} = unitsH[i];
unitsH[i].siValue = +value;
unitsH[i].usValue = +(value / factor).toFixed(2);
}
function setBothFromUSH(value, i) {
const {factor, usValue} = unitsH[i];
unitsH[i].usValue = +value;
unitsH[i].siValue = +(value * factor).toFixed(2);
}
</script>
使用简化的 html 代码:
<VirtualList items={filteredList} bind:start bind:end let:item >
<div class="border" style="overflow-x: scroll;"> <div><div>
<div class="name">{item.name}</div>
<span>Specimen: {item.specimen} </span>
<span> Conversion Factor: {item.factor} </span>
</div>
<div>
<label>US Range:{item.conventionalRange} {item.conventionalUnit}</label>
<input name="us{filteredList.indexOf(item)}" value={item.usValue} on:input="{e => setBothFromUSH(e.target.value, filteredList.indexOf(item))}" type=number placeholder=" US">
</div>
<div>
<label>SI Range: {item.siRange} {item.siUnit}</label>
<input name="si{filteredList.indexOf(item)}" value={item.siValue} on:input="{e => setBothFromSIH(e.target.value, filteredList.indexOf(item))}" type=number placeholder="SI">
</div></div> </div>
</VirtualList>
<p>showing items {start}-{end}</p>
感谢您提供的任何帮助使它正常工作!
这是您的过滤器的一个小问题。您将产品名称转换为小写,而不是过滤条件;) 如果您输入 acetone
而不是 Acetone
,那么它会起作用。修复:
$: filteredList = unitsH.filter(item => item.name.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1);
编辑:
不为某些过滤元素调用函数的问题是您显示 filteredList
但仍然在 unitsH
列表上进行查找。把它改成这样就可以了:
function setBothFromSIH(value, i) {
const {factor, siValue} = filteredList[i];
filteredList[i].siValue = +value;
filteredList[i].usValue = +(value / factor).toFixed(2);
}
function setBothFromUSH(value, i) {
const {factor, usValue} = filteredList[i];
filteredList[i].usValue = +value;
filteredList[i].siValue = +(value * factor).toFixed(2);
}
祝您黑客愉快!
您的问题是由于使用了错误的索引引起的,在更改处理程序中您传递了 filteredIndex
中项目的索引,但随后您使用该索引更改了数组中该索引上的项目 unitsH
.
您可以通过以下方式查看: - 重新开始 - 注意对乙酰氨基酚的值(索引 0) - 搜索锌 - 更改锌的值(过滤列表中的索引 0) - 清除搜索
->> 对乙酰氨基酚已更改,因为它是单位 H 中的索引 0
您可以通过传入原始数组的索引轻松解决此问题:
<input name="si{filteredList.indexOf(item)}" value={item.siValue} on:input="{e => setBothFromSIH(e.target.value, unitsH.indexOf(item))}" type=number placeholder="SI">
但是,如果您将每个项目的标记移动到一个单独的组件,您可以通过直接与属性交互而不是尝试在数组中更改它们来极大地简化它。