Svelte todo 应用程序错误:不显示表单验证错误

Svelte todo app bug: form validation errors do not show up

出于学习目的,我正在使用 Svelte 开发一个小型 ToDo 应用程序(我是 Svelte 的新手)。

我在尝试向 New Todo 表单添加验证错误时遇到困难。

在我拥有的 <script> 个标签内

var errors = [];

function addTodo(){
    
    //Empty todo object
    let newTodo = {};
    
    //Set new todo object's properties (id, title, completed)
    if (todos.length == 0) {
        newTodo.id = 1;
    } else {
        newTodo.id = todos[0].id + 1;
    }
    
    if(document.querySelector('#new_todo').value.length < 3){
        errors.push('Please introduce at least 3 characters');
    } else {
        newTodo.title = document.querySelector('#new_todo').value;
    }
    
    newTodo.completed = false;
    
    //Add new todo
    if (errors === undefined || errors.length == 0) {
        todos.unshift(newTodo);
    }
    todos = todos;
    
    //Empty field when done adding todo
    document.querySelector('#new_todo').value = '';
}

在视图中:

{#if errors.length > 0}
    <div class="m-2 alert alert-danger">
        {#each errors as error}
            <p>{error}</p>
        {/each}
     </div>
{/if}
    
<div class="input-group p-2" id="addForm">
    <input type="text" class="form-control" id="new_todo" placeholder="New Todo">
    <div class="input-group-append">
        <button on:click="{addTodo}" class="btn btn-sm btn-success">Add</button>
    </div>
</div>

由于我无法找到的原因,未出现错误验证消息并且控制台显示 Uncaught (in promise): if_block0.p is not a function

查看 REPL here

我的错误在哪里?

您需要将 errors 数组的更改通知 Svelte:

errors.push('Please introduce at least 3 characters')
errors = errors

Svelte 不跟踪对象突变,仅跟踪分配(即 =)。但我想您已经知道了,因为您的组件中已经有类似的代码。

话虽如此,我认为您遇到的错误可能被视为 Svelte 中的错误。但这可能不会影响有用的用例——即改变反应变量,但不希望 Svelte 反映更改。

此外,不相关,但我强烈建议不要在今天编写的任何 JS 代码中对变量使用 var 关键字,尤其是在 Svelte 组件中,它可能会混淆您是否希望它响应(let) 或也不 (const).

编辑

您可能还应该依靠 Svelte 来访问输入字段的值,而不是使用 document.querySelector

像这样:

<script>
  ...

  let newTodoValue = ''

  const addTodo = () => {
    if (newTodoValue.length < 3) {
      errors.push('Too short')
      errors = errors
    }

    ...
    
    // clear the value
    newTodoValue = ''
  }
</script>

<input type="text" class="form-control" bind:value={newTodoValue} />

您很少需要直接在 Svelte 等声明式框架中使用 DOM API(例如 querySelector)。如果您需要访问元素本身,通常 bind:this 或使用 Svelte 中的操作会更好。

更换

问题完全解决
if(document.querySelector('#new_todo').value.length < 3){
    errors.push('Please introduce at least 3 characters');
} else {
    newTodo.title = document.querySelector('#new_todo').value;
}

if(document.querySelector('#new_todo').value.length < 3){
    errors.push('Please introduce at least 3 characters');
    errors = errors; // new line
} else {
    newTodo.title = document.querySelector('#new_todo').value;
    errors = []; // new line
}