如何将这个todo列表与Svelte的即时搜索结合起来



tldr版本的EDIT向下滚动到下面代码中的我非常接近的地方

问题

我有一个基本的待办事项列表,当完成时将具有以下品质:

  1. 当页面加载时,表单字段应处于焦点位置
  2. 当用户单击向上/向下箭头时,应通过CSS背景色更改来选择列表中的项目
  3. 当用户在表单中键入新项目时,该项目应显示在用户的列表中
  4. 当用户在表单字段中键入";即时搜索";应用于列表,并且只显示与搜索匹配的项目。所有其他功能应该仍然有效。当用户使用向上/向下箭头滚动时,无论页面上显示了多少项目,它都应该仍然有效。如果只显示两个项目,则用户应该能够使用上下箭头来选择这两个项目和表单字段焦点

除数字4外的所有项目似乎都能正常工作。以下代码演示项目1-3

https://svelte.dev/repl/214b9c033d1c489e991484d387c267c2?version=3.30.0

<script>
import { onMount } from 'svelte';
let clients = ["a Little piggy","b little piggy","c little piggy"]; 
let indexVal = -1;
let downArrowPress = 40;
let upArrowPress = 38;
let clientInputTextField = "";
let clientVal = "";
onMount(function() {
clientInputTextField.focus();
});

function handleKeydown(event) {
if(event.keyCode === upArrowPress) {
indexVal-=1;    
indexVal = indexVal < 0 ?  clients.length : indexVal
console.log(indexVal);
}
if(event.keyCode === downArrowPress) {
indexVal+=1;
indexVal = indexVal > clients.length ?  0 : indexVal
console.log(indexVal);
}
if(indexVal > clients.length -1 || indexVal < 0){
clientInputTextField.focus(); 
} else {
clientInputTextField.blur()
}   
}

function handleSubmit(e) {
const value = e.target.input.value;
console.log(value);
clients = [...clients, value];
clientVal = "";
}
</script>

<svelte:window on:keydown={handleKeydown}/>
<form on:submit|preventDefault={handleSubmit}>
<input type="text" name="input" bind:this={clientInputTextField}  bind:value={clientVal} autocomplete="off">
<input type="submit" name="">
</form>
<ul>
{#each clients as client, i}
{#if i === indexVal}
<li style="background-color:orange">{client}</li>
{:else}
<li style="">{client}</li>
{/if}
{/each}
</ul>


<!-- 
function search(e){
console.log(e.target.value)
const searchString = e.target.value.toLowerCase();
const filteredCharacters = clients.filter((character) => {
return (
character.toLowerCase().includes(searchString) ||
character.toLowerCase().includes(searchString)
);
});

console.log(filteredCharacters)
}
-->

我想把上面的代码与即时搜索功能结合起来。

function search(e){
console.log(e.target.value)
const searchString = e.target.value.toLowerCase();
const filteredCharacters = clients.filter((character) => {
return (
character.toLowerCase().includes(searchString) ||
character.toLowerCase().includes(searchString)
);
});

console.log(filteredCharacters)
}

到目前为止,我所尝试的一切都会变得一团糟,没有返回列表,也没有对输入字段进行聚焦(onBlur(。

console.log下面的代码是一个数组,它在用户搜索时提供了我想要的内容。下一步是将其应用于DOM。到目前为止,我所尝试的一切都没有奏效。

https://svelte.dev/repl/ceca685a3a4c49b4b5ccd780a101fc63?version=3.30.0

<script>
import { onMount } from 'svelte';
let clients = ["a Little piggy","b little piggy","c little piggy"]; 
let indexVal = -1;
let downArrowPress = 40;
let upArrowPress = 38;
let clientInputTextField = "";
let clientVal = "";
onMount(function() {
clientInputTextField.focus();
});

function search(e){
console.log(e.target.value)
const searchString = e.target.value.toLowerCase();
const filteredCharacters = clients.filter((character) => {
return (
character.toLowerCase().includes(searchString) ||
character.toLowerCase().includes(searchString)
);
});

console.log(filteredCharacters)

}

function handleKeydown(event) {
if(event.keyCode === upArrowPress) {
indexVal-=1;    
indexVal = indexVal < 0 ?  clients.length : indexVal
console.log(indexVal);
}
if(event.keyCode === downArrowPress) {
indexVal+=1;
indexVal = indexVal > clients.length ?  0 : indexVal
console.log(indexVal);
}
if(indexVal > clients.length -1 || indexVal < 0){
clientInputTextField.focus(); 
} else {
clientInputTextField.blur()
}   
}

function handleSubmit(e) {
const value = e.target.input.value;
console.log(value);
clients = [...clients, value];
clientVal = "";
}
</script>

<svelte:window on:keydown={handleKeydown}/>
<form on:submit|preventDefault={handleSubmit}>
<input type="text" name="input" bind:this={clientInputTextField}  bind:value={clientVal} on:input={search} autocomplete="off">
<input type="submit" name="">
</form>
<ul>
{#each clients as client, i}
{#if i === indexVal}
<li style="background-color:orange">{client}</li>
{:else}
<li style="">{client}</li>
{/if}
{/each}
</ul>


<!-- 

-->

编辑

我在下面的代码中非常接近

在这个版本中,唯一的问题是当用户提交一个新的todo时,列表不会出现在DOM中。幕后的其他一切都起作用。要了解我的意思,请在输入字段中添加一个项目,提交它,然后在表单字段中键入字母a,然后点击空格键。列表将重新出现。

https://svelte.dev/repl/f8fb733401eb4e27b9b8e54c688d355a?version=3.30.0

<script>
import { onMount } from 'svelte';
let clients = ["a Little piggy","b little piggy","c little piggy"]; 
let clientsCopy = [...clients];
let indexVal = -1;
let downArrowPress = 40;
let upArrowPress = 38;
let clientInputTextField = "";
let clientVal = "";
onMount(function() {
clientInputTextField.focus();
});

function search(e){
console.log(e.target.value)
const searchString = e.target.value.toLowerCase();
const filteredCharacters = clients.filter((character) => {
return (
character.toLowerCase().includes(searchString) ||
character.toLowerCase().includes(searchString)
);
});

clientsCopy = [...filteredCharacters]

}

function handleKeydown(event) {
if(event.keyCode === upArrowPress) {
indexVal-=1;    
indexVal = indexVal < 0 ?  clientsCopy.length : indexVal
console.log(indexVal);
}
if(event.keyCode === downArrowPress) {
indexVal+=1;
indexVal = indexVal > clientsCopy.length ?  0 : indexVal
console.log(indexVal);
}
if(indexVal > clientsCopy.length -1 || indexVal < 0){
clientInputTextField.focus(); 
} else {
clientInputTextField.blur()
}   
}

function handleSubmit(e) {
const value = e.target.input.value;
console.log(value);
clients = [...clients, value];
clientVal = "";
}
</script>

<svelte:window on:keydown={handleKeydown}/>
<form on:submit|preventDefault={handleSubmit}>
<input type="text" name="input" bind:this={clientInputTextField}  bind:value={clientVal} on:input={search} autocomplete="off">
<input type="submit" name="">
</form>
<ul>
{#each clientsCopy as client, i}
{#if i === indexVal}
<li style="background-color:orange">{client}</li>
{:else}
<li style="">{client}</li>
{/if}
{/each}
</ul>


<!-- 

-->

我得到了它。我将客户端数组的副本设置为反应数组。希望这能帮助到别人。

https://svelte.dev/repl/ad1c185bf97a47b98506c3603f510de6?version=3.30.0

<script>
import { onMount } from 'svelte';
let clients = ["a Little piggy","b little piggy","c little piggy"]; 
$: clientsCopy = clients ;
let indexVal = -1;
let downArrowPress = 40;
let upArrowPress = 38;
let clientInputTextField = "";
let clientVal = "";
onMount(function() {
clientInputTextField.focus();
});

function search(e){
console.log(e.target.value)
const searchString = e.target.value.toLowerCase();
const filteredCharacters = clients.filter((character) => {
return (
character.toLowerCase().includes(searchString) ||
character.toLowerCase().includes(searchString)
);
});

clientsCopy = [...filteredCharacters]

}

function handleKeydown(event) {
if(event.keyCode === upArrowPress) {
indexVal-=1;    
indexVal = indexVal < 0 ?  clientsCopy.length : indexVal
console.log(indexVal);
}
if(event.keyCode === downArrowPress) {
indexVal+=1;
indexVal = indexVal > clientsCopy.length ?  0 : indexVal
console.log(indexVal);
}
if(indexVal > clientsCopy.length -1 || indexVal < 0){
clientInputTextField.focus(); 
} else {
clientInputTextField.blur()
}   
}

function handleSubmit(e) {
const value = e.target.input.value;
console.log(value);
clients = [...clients, value];
clientVal = "";
}
</script>

<svelte:window on:keydown={handleKeydown}/>
<form on:submit|preventDefault={handleSubmit}>
<input type="text" name="input" bind:this={clientInputTextField}  bind:value={clientVal} on:input={search} autocomplete="off">
<input type="submit" name="">
</form>
<ul>
{#each clientsCopy as client, i}
{#if i === indexVal}
<li style="background-color:orange">{client}</li>
{:else}
<li style="">{client}</li>
{/if}
{/each}
</ul>


<!-- 

-->

这是一个更简洁的版本,基于这里的要点中的代码。它实际上与您的解决方案相同(即创建并显示一个单独的"过滤"列表(!

<script>
import { onMount } from 'svelte';
let clients = ["a Little piggy","b little piggy","c little piggy"]; 
let indexVal = -1;
let downArrowPress = 40;
let upArrowPress = 38;
let clientInputTextField = "";
let clientVal = "";

const startsWith = (item, query) => item.toLowerCase().indexOf(query.toLowerCase()) != -1;
$: filteredClients = clientVal && clientVal.length ? clients.filter(item => startsWith(item, clientVal)) : clients;

onMount(function() {
clientInputTextField.focus();
});

function handleKeydown(event) {
if(event.keyCode === upArrowPress) {
indexVal-=1;    
indexVal = indexVal < 0 ?  clients.length : indexVal
console.log(indexVal);
}
if(event.keyCode === downArrowPress) {
indexVal+=1;
indexVal = indexVal > clients.length ?  0 : indexVal
console.log(indexVal);
}
if(indexVal > clients.length -1 || indexVal < 0){
clientInputTextField.focus(); 
} else {
clientInputTextField.blur()
}   
}

function onChange(e) {
console.log("what")
const searchTerm = e.target.value.toLowerCase();
console.log(searchTerm)
clients = clients.filter(client => client.toLowerCase().includes(searchTerm))
}

function handleSubmit(e) {
const value = e.target.input.value;
console.log(value);
clients = [...clients, value];
clientVal = "";
}
</script>

<svelte:window on:keydown={handleKeydown}/>
<form on:submit|preventDefault={handleSubmit}>
<!--     <input type="text" name="input" on:change={onChange} bind:this={clientInputTextField}  bind:value={clientVal} autocomplete="off"> -->
<input type="text" name="input" bind:this={clientInputTextField}  bind:value={clientVal} autocomplete="off">
<input type="submit" name="">
</form>
<ul>
{#each filteredClients as client, i}
{#if i === indexVal}
<li style="background-color:orange">{client}</li>
{:else}
<li style="">{client}</li>
{/if}
{/each}
</ul>

最新更新