【问题标题】:Svelte application bug: global.css overwrites component-level CSSSvelte 应用程序错误:global.css 覆盖组件级 CSS
【发布时间】:2020-07-17 14:21:39
【问题描述】:

在一个 Svelte 应用程序中,我有一个带有简单验证的表单。

表格

<form id="surveyForm" class="mt-4">
    <div class="form-group">
      <input type="text" class="form-control" placeholder="First name">
    </div>
    <div class="form-group">
      <input type="text" class="form-control" placeholder="Last name">
    </div>
    <button class="btn btn-full" on:click={Continue}>Continue</button>
</form>

验证:

import {fly, fade} from 'svelte/transition';
let hasError = false;
let errMessage = "";
let isSuccessVisible = false;

function validateInput() {
    var surveyForm = document.getElementById('surveyForm'),
        inputFields = surveyForm.querySelectorAll('input[type=text]');

    hasError = false;

    inputFields.forEach(function(field) {
        field.classList.remove("is-invalid");
        var inputFieldVal = field.value;
        if (inputFieldVal.length == 0) {
            field.classList.add("is-invalid");
            hasError = true;
        }
    });
    errMessage = "All the fileds are mandatory";
}


function Continue(e) {
    e.preventDefault();
    validateInput();
    if (hasError == false) {
        isSuccessVisible = true;

        setTimeout(function() {
            isSuccessVisible = false;
        }, 3000);
    }
}

为了给无效的表单域加上红色边框,我使用border: 1px solid #c00 !important

.error-alert {
    border: 1px solid #c00 !important;
    color: #c00;
}

is-invalid 类已正确添加(和删除),但默认的 global.css 样式覆盖了我的组件级样式,如您在此 REPL 中所见

为什么会这样?什么是可靠的修复方法?


注意:所描述的案例是一个简化的案例,实际上我可能需要其他验证,例如确保值是数字。我必须实施的解决方案不是一个非常具体的解决方案。

【问题讨论】:

    标签: javascript css svelte


    【解决方案1】:

    在 REPL 中,您会看到以下警告:

    未使用的 CSS 选择器 (87:1)

    那是因为.is-invalid 选择器没有在标记中的任何地方使用——如果一个类名未被使用,Svelte 会告诉你它并删除它。为了让 Svelte 能够“看到”它,它必须在标记中——您不能使用 classList 以编程方式添加它。 (这是一项功能,而不是错误:以编程方式操作 DOM 将不可避免地导致您的视图与您的状态不同步。)

    不过,在这种情况下,您不需要向输入元素添加类,或者在函数内部进行检查。您可以只使用输入的required 属性和:invalid CSS 选择器:

    <input type="text" class="form-control" placeholder="First name" required>
    
    input:invalid {
      border: 1px solid #c00;
    }
    

    :invalid 状态将在用户提交任何数据之前应用,因此您可能需要添加一个类来指示用户是否已尝试提交:

    <form id="surveyForm" class="mt-4" class:submitted>
      <div class="form-group">
        <input type="text" class="form-control" placeholder="First name" required>
      </div>
    
      <!-- ... -->
    </form>
    
    .submitted input:invalid {
      border: 1px solid #c00;
    }
    

    添加该类的最简单方法是在按钮上的click 事件处理程序中。

    Here's a demo.

    使用您在 HTML 中免费获得的内容还有其他好处。例如,只要存在验证错误,表单就不会提交(并且验证不限于“必需”——您可以强制指定特定模式,或使用例如type="email" 来要求有效的电子邮件地址等),这意味着在您的 submit 事件处理程序中,您已经知道输入是有效的。

    【讨论】:

    • 感谢您提醒我尽可能利用 HTML,我经常忽略这一点而感到内疚。为了恢复全局错误/成功警报,我冒昧地稍微修改了您的 REPL:svelte.dev/repl/70bb412acad94c3ab4bc54e5bb3da312?version=3.24.0
    • 很好,但是如果我需要其他验证,例如确保值是数字,该怎么办?
    • 您也可以回答this的问题吗?谢谢!
    • 嗨。请帮我处理 this question。谢谢!
    【解决方案2】:

    您可以通过使用 HTML5 客户端表单验证来使用 Rich 描述的其他验证技术。更多信息请访问MDN

    <form id="surveyForm" class="mt-4" class:submitted>
        <div class="form-group">
        <input type="text" class="form-control" placeholder="First name" required>
      </div>
        <div class="form-group">
        <input type="text" class="form-control" placeholder="Last name" required>
      </div>
        <div class="form-group">
        <input type="number" class="form-control" placeholder="Enter a number" required>
      </div>
        <div class="form-group">
        <input type="email" class="form-control" placeholder="Email" required>
      </div>
        <div class="form-group">
        <input type="date" class="form-control" placeholder="Date" required>
      </div>
      <button class="btn btn-full" on:click|preventDefault={Continue}>Continue</button>
    </form>
    

    REPL

    如果您不想使用它 - 或者由于某种原因它没有涵盖您的所有用例 - 您可以使用 Svelte 操作类,而不是直接访问 DOM:

    <div class="form-group">
        <input bind:value={second} type="text" class="form-control" class:is-invalid="{ submitted && second.length == 0 }" placeholder="Last name">
    </div>
    

    REPL

    Svelte 删除您的 .is-invalid 样式的原因是 Svelte 不使用它。在这种情况下我不会推荐它,但您可以使用 :global() 强制 Svelte 保持样式:

    :global(.is-invalid) {
        border: 1px solid #c00;
    }
    

    REPL

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-21
      • 2010-11-10
      • 1970-01-01
      • 1970-01-01
      • 2019-08-17
      • 2021-12-21
      • 1970-01-01
      相关资源
      最近更新 更多