代码之家  ›  专栏  ›  技术社区  ›  Razvan Zamfir

苗条的应用程序缺陷:全局性。css覆盖组件级css

  •  0
  • Razvan Zamfir  · 技术社区  · 6 年前

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

    表格

    <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 .

    为什么会这样?什么是可靠的解决方案?


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

    0 回复  |  直到 6 年前
        1
  •  5
  •   Rich Harris    6 年前

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

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

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

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

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

    这个 :无效 但是,状态将在用户提交任何数据之前应用,因此您可能希望添加一个类,指示用户是否已经尝试提交:

    <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 事件处理程序,您已经知道输入是有效的。

        2
  •  2
  •   digby280    6 年前

    通过使用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

    苗条的原因是去除你的皮肤 .is-invalid 时尚是因为Svelte不使用它。在这种情况下,我不推荐它,但你可以使用 :global() :

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

    REPL