SVELTE 中即时搜索和列表选择的几个问题

A couple of problems with instant search and list selection in SVELTE

我有下面的代码。预期行为如下:

  1. 当页面加载时,表单域应该处于焦点。
  2. 当用户单击 up/down 箭头时,应通过 CSS 背景颜色更改来选择列表中的项目。
  3. 当用户在表单字段中键入内容时,“即时搜索”将应用于列表,并且只会显示与搜索相匹配的项目。
  4. 如果用户键入了不在列表中的项目并提交了该项目,页面应自动更新以显示列表和列表中的新项目。

在第 4 步之前一切似乎都正常。如果您尝试将项目提交到列表,页面不会更新新项目并且表单失去焦点。

我之前使用 ref 和 useEffect 使用 React 创建了这个脚本。我正在探索 SVELTE 以查看类似脚本的外观。

谢谢!

交互示例:

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

<script>
    import { onMount } from 'svelte';
    let clients = ["a Little piggy","b little piggy","c little piggy"]; //hard coded api data
    let clientsClone = [...clients];
    let indexVal = -1;
    let downArrowPress = 40;
    let upArrowPress = 38;
    let clientInputTextField = "";
    let selectedClient = "";

     //______________________BEGIN focus input field on page load

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

     //_______________________END focus input field on page load.


     // ______________________BEGIN instant search algorithm 
    function instantSearch(query,listArr) {
        let arr = [...listArr]
        let newList = []

       arr.map(val =>{
            query.split(" ").map(word =>{
                if(val.toLowerCase().indexOf(word.toLowerCase()) != -1){
                    newList.push(val)
                }
            })
       })
       
       console.log(newList)
       return newList
    }
    //_________________________END instant search algorithm


    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 searchItems(event){
        console.log(event.target.value)
        let result = instantSearch(event.target.value, clients);
        clientsClone = [...result]
        console.log(result)
        
     }


     function handleSubmit(){
  
        console.log(selectedClient)
        clients.push(selectedClient)
        selectedClient = "";


     }




</script>


<svelte:window on:keydown={handleKeydown}/>

<form on:submit|preventDefault={handleSubmit}>
    <input type="text" name=""  on:input={searchItems} bind:this={clientInputTextField} bind:value={selectedClient}>
    <input type="submit" name="">
</form>



<ul>
    {#each clientsClone 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/a52d1935209f4cbbb8289b0096374288?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 = "";



     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()
        }
    
     }






</script>


<svelte:window on:keydown={handleKeydown}/>

<form>
    <input type="text" name="" bind:this={clientInputTextField} >
    <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>

您需要将事件处理程序附加到侦听 submit 事件的表单。要获取 input 字段的值,您还需要为其提供 name 属性:

<form on:submit|preventDefault={handleSubmit}>
    <input type="text" name="input" bind:this={clientInputTextField} >
    <input type="submit" name="">
</form>

请注意,preventDefault 修饰符会阻止页面实际提交表单(即更改 URL)。根据您的用例,您可能不希望出现此行为。

然后更新您的 clients 列表,您可以像这样定义一个简单的 handleSubmit 函数:

function handleSubmit(e) {
    const value = e.target.input.value;
    clients = [...clients, value]
}

将此添加到您编辑的代码后,完整示例如下所示:


<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 = "";

    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]
    }
</script>

<svelte:window on:keydown={handleKeydown}/>

<form on:submit|preventDefault={handleSubmit}>
    <input type="text" name="input" bind:this={clientInputTextField} >
    <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>