表单的自定义和样式设计已经非常困难了,以至于我们已经开始看到一些更灵活控制的新想法。但我们通常不讨论的是设计除验证之外的良好表单体验。这就是 Jima Victor 在本文中讨论的内容,重点关注创建涉及各部分之间导航的多步骤表单。
对于多步骤表格,规划包括按逻辑方式组织各个步骤的问题、对类似问题进行分组以及尽量减少步骤数量和每个步骤所需的信息量。应以让每个步骤重点突出且易于管理为目标。
在本教程中,我们将为工作申请创建一个多步骤表单。以下是我们将在每个步骤向申请人索取的详细信息:
个人信息
收集申请人的姓名、电子邮件和电话号码。工作经验
收集申请人的最近的公司、职位和工作年限。技能和资格
申请人列出他们的技能并选择他们的最高学位。审核并提交
此步骤不会收集任何信息。相反,它为申请人提供了一个机会,让他们可以在提交表格之前返回并审核在表格的前面步骤中输入的信息。
你可以将这些问题视为一种数字方式来了解某人。你不能在第一次见面时询问他们的工作经历而不先问他们的名字。
根据上面的步骤,我们的表单 HTML 主体应该是这样的。首先,主要<form>
元素:
<form id="jobApplicationForm"> <!-- Step 1: Personal Information --> <!-- Step 2: Work Experience --> <!-- Step 3: Skills & Qualifications --> <!-- Step 4: Review & Submit --> </form>
第一步是填写个人信息,如申请人的姓名、电子邮件地址和电话号码:
<form id="jobApplicationForm"> <!-- Step 1: Personal Information --> <fieldset class="step" id="step-1"> <legend id="step1Label">Step 1: Personal Information</legend> <label for="name">Full Name</label> <input type="text" id="name" name="name" required /> <label for="email">Email Address</label> <input type="email" id="email" name="email" required /> <label for="phone">Phone Number</label> <input type="tel" id="phone" name="phone" required /> </fieldset> <!-- Step 2: Work Experience --> <!-- Step 3: Skills & Qualifications --> <!-- Step 4: Review & Submit --> </form>
申请人完成第一步后,我们将引导他们进入第二步,重点关注他们的工作经历,以便我们收集他们最近的公司、职位和工作年限等信息。我们将<fieldset>
根据这些输入添加新内容:
<form id="jobApplicationForm"> <!-- Step 1: Personal Information --> <!-- Step 2: Work Experience --> <fieldset class="step" id="step-2" hidden> <legend id="step2Label">Step 2: Work Experience</legend> <label for="company">Most Recent Company</label> <input type="text" id="company" name="company" required /> <label for="jobTitle">Job Title</label> <input type="text" id="jobTitle" name="jobTitle" required /> <label for="yearsExperience">Years of Experience</label> <input type="number" id="yearsExperience" name="yearsExperience" min="0" required /> </fieldset> <!-- Step 3: Skills & Qualifications --> <!-- Step 4: Review & Submit --> </form>
第三步是申请人列出他们所申请职位所需的技能和资格:
<form id="jobApplicationForm"> <!-- Step 1: Personal Information --> <!-- Step 2: Work Experience --> <!-- Step 3: Skills & Qualifications --> <fieldset class="step" id="step-3" hidden> <legend id="step3Label">Step 3: Skills & Qualifications</legend> <label for="skills">Skill(s)</label> <textarea id="skills" name="skills" rows="4" required></textarea> <label for="highestDegree">Degree Obtained (Highest)</label> <select id="highestDegree" name="highestDegree" required> <option value="">Select Degree</option> <option value="highschool">High School Diploma</option> <option value="bachelor">Bachelor's Degree</option> <option value="master">Master's Degree</option> <option value="phd">Ph.D.</option> </select> </fieldset> <!-- Step 4: Review & Submit --> <fieldset class="step" id="step-4" hidden> <legend id="step4Label">Step 4: Review & Submit</legend> <p>Review your information before submitting the application.</p> <button type="submit">Submit Application</button> </fieldset> </form>
最后,我们允许申请人在提交之前检查自己的信息:
<form id="jobApplicationForm"> <!-- Step 1: Personal Information --> <!-- Step 2: Work Experience --> <!-- Step 3: Skills & Qualifications --> <!-- Step 4: Review & Submit --> <fieldset class="step" id="step-4" hidden> <legend id="step4Label">Step 4: Review & Submit</legend> <p>Review your information before submitting the application.</p> <button type="submit">Submit Application</button> </fieldset> </form>
注意:我们hidden
为除第一个元素之外的每个元素添加了一个属性fieldset
。这确保用户只看到第一步。完成第一步后,他们可以通过单击导航按钮继续填写第二步的工作经历。我们稍后会添加此按钮。
添加样式
为了保持重点,我们不会在本教程中强调样式。为了保持简单,我们将利用Simple.css 样式框架来使表单在本教程的其余部分保持良好状态。
如果你跟着我做的话,我们可以在文档中包含 Simple 的样式<head>
:
<link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css" />
然后从那里继续创建一个style.css
包含我折叠的以下样式的文件。
<details> <summary>View CSS</summary> body { min-height: 100vh; display: flex; align-items: center; justify-content: center; } main { padding: 0 30px; } h1 { font-size: 1.8rem; text-align: center; } .stepper { display: flex; justify-content: flex-end; padding-right: 10px; } form { box-shadow: 0px 0px 6px 2px rgba(0, 0, 0, 0.2); padding: 12px; } input, textarea, select { outline: none; } input:valid, textarea:valid, select:valid, input:focus:valid, textarea:focus:valid, select:focus:valid { border-color: green; } input:focus:invalid, textarea:focus:invalid, select:focus:invalid { border: 1px solid red; } </details>
表单导航和验证
对于多步骤表单,一个破坏用户体验的简单方法是等到用户进入表单的最后一步才告知他们在此过程中犯的任何错误。在进入下一步之前,应验证表单的每个步骤是否存在错误,并显示描述性错误消息,以使用户了解错误所在以及如何修复。
现在,表单中唯一可见的部分是第一步。要完成表单,用户需要能够导航到其他步骤。我们将使用多个按钮来实现这一点。第一步将有一个Next按钮。第二步和第三步将有一个Previous和Next按钮,第四步将有一个Previous和Submit按钮。
<form id="jobApplicationForm"> <!-- Step 1: Personal Information --> <fieldset> <!-- ... --> <button type="button" class="next" onclick="nextStep()">Next</button> </fieldset> <!-- Step 2: Work Experience --> <fieldset> <!-- ... --> <button type="button" class="previous" onclick="previousStep()">Previous</button> <button type="button" class="next" onclick="nextStep()">Next</button> </fieldset> <!-- Step 3: Skills & Qualifications --> <fieldset> <!-- ... --> <button type="button" class="previous" onclick="previousStep()">Previous</button> <button type="button" class="next" onclick="nextStep()">Next</button> </fieldset> <!-- Step 4: Review & Submit --> <fieldset> <!-- ... --> <button type="button" class="previous" onclick="previousStep()">Previous</button> <button type="submit">Submit Application</button> </fieldset> </form>
注意:我们为和按钮添加了onclick
属性,以将它们链接到各自的 JavaScript 函数:和。PreviousNextpreviousStep()
nextStep()
“下一步”按钮
该nextStep()
功能与“下一步”按钮相关联。每当用户单击“下一步”按钮时,该nextStep()
功能都会首先检查以确保用户当前所处步骤的所有字段均已正确填写,然后才进入下一步。如果字段填写不正确,它会显示一些错误消息,让用户知道他们做错了什么,并告知他们如何做才能消除错误。
在开始实现该nextStep
函数之前,我们需要定义一些变量,因为函数中需要用到它们。首先,我们需要 DOM 中的输入字段,这样我们就可以对它们进行检查,确保它们是有效的。
// Step 1 fields const name = document.getElementById("name"); const email = document.getElementById("email"); const phone = document.getElementById("phone"); // Step 2 fields const company = document.getElementById("company"); const jobTitle = document.getElementById("jobTitle"); const yearsExperience = document.getElementById("yearsExperience"); // Step 3 fields const skills = document.getElementById("skills"); const highestDegree = document.getElementById("highestDegree");
然后,我们需要一个数组来存储错误消息。
let errorMsgs = [];
此外,我们需要在 DOM 中创建一个元素,用于在生成错误消息后插入这些消息。此元素应放置在 HTML 中最后一个fieldset
结束标记的正下方:
<div id="errorMessages" style="color: rgb(253, 67, 67)"></div>
div
使用以下行将上述内容添加到 JavaScript 代码中:
const errorMessagesDiv = document.getElementById("errorMessages");
现在我们已经有了所有变量,下面是函数的实现nextstep()
:
function nextStep() { errorMsgs = []; errorMessagesDiv.innerText = ""; switch (currentStep) { case 1: addValidationErrors(name, email, phone); validateStep(errorMsgs); break; case 2: addValidationErrors(company, jobTitle, yearsExperience); validateStep(errorMsgs); break; case 3: addValidationErrors(skills, highestDegree); validateStep(errorMsgs); break; } }
按下按钮的那一刻Next,我们的代码首先检查用户当前处于哪个步骤,并根据此信息,通过调用addValidationErrors()
函数来验证该特定步骤的数据。如果有错误,我们会显示它们。然后,表单调用该validateStep()
函数来验证在进入下一步之前没有错误。如果有错误,它会阻止用户继续下一步。
每当nextStep()
函数运行时,都会先清除错误消息,以避免将不同步骤中的错误附加到现有错误中或函数运行时重新添加现有错误消息addValidationErrors
。该addValidationErrors
函数会针对每个步骤调用,并使用该步骤的字段作为参数。
addValidationErrors
该功能的实现方式如下:
function addValidationErrors(fieldOne, fieldTwo, fieldThree = undefined) { if (!fieldOne.checkValidity()) { const label = document.querySelector(`label[for="${fieldOne.id}"]`); errorMsgs.push(`Please Enter A Valid ${label.textContent}`); } if (!fieldTwo.checkValidity()) { const label = document.querySelector(`label[for="${fieldTwo.id}"]`); errorMsgs.push(`Please Enter A Valid ${label.textContent}`); } if (fieldThree && !fieldThree.checkValidity()) { const label = document.querySelector(`label[for="${fieldThree.id}"]`); errorMsgs.push(`Please Enter A Valid ${label.textContent}`); } if (errorMsgs.length > 0) { errorMessagesDiv.innerText = errorMsgs.join("\n"); } }
该函数的定义如下validateStep()
:
function validateStep(errorMsgs) { if (errorMsgs.length === 0) { showStep(currentStep + 1); } }
该validateStep()
函数检查是否存在错误。如果没有错误,它将在函数的帮助下继续下一步showStep()
。
function showStep(step) { steps.forEach((el, index) => { el.hidden = index + 1 !== step; }); currentStep = step; }
此showStep()
函数需要 DOM 中的四个字段集。将以下行添加到 JavaScript 代码顶部以使字段集可用:
const steps = document.querySelectorAll(".step");
该showStep()
函数的作用是检查fieldsets
表单中的所有内容,并隐藏与fieldset
我们要导航到的步骤不相等的内容。然后,它会更新currentStep
变量,使其等于我们要导航到的步骤。
“上一个”
该previousStep()
函数与按钮相链接Previous。每当单击上一个按钮时,与该nextStep
函数类似,错误消息也会从页面中清除,并且导航也由该showStep
函数处理。
function previousStep() { errorMessagesDiv.innerText = ""; showStep(currentStep - 1); }
每当showStep()
使用“ ”作为参数调用函数时currentStep - 1
(如本例),我们都会回到上一步,而每当使用showStep()
“ currentStep + 1
”作为参数调用函数时(如函数的情况validateStep()
),我们就会进入下一步。
通过视觉提示改善用户体验
改善多步骤表单用户体验的另一种方法是集成视觉提示,这些提示可以为用户提供有关其所处流程的反馈。这些提示可以包括进度指示器或步进器,以帮助用户了解他们所处的确切步骤。
集成步进器
要将步进器集成到我们的表单中(有点像来自 Material Design 的这个),我们需要做的第一件事就是将其添加到 HTML 的开启标签下方<form>
。
<form id="jobApplicationForm"> <div class="stepper"> <span><span class="currentStep">1</span>/4</span> </div> <!-- ... --> </form>
接下来,我们需要查询步进器中代表当前步骤的部分。这是类名为 的 span 标签currentStep
。
const currentStepDiv = document.querySelector(".currentStep");
现在,每当单击上一个或下一个按钮时,我们都需要更新步进值。为此,我们需要showStep()
通过向函数附加以下行来更新该函数:
currentStepDiv.innerText = currentStep;
这行代码之所以添加到showStep()
函数中,是因为该showStep()
函数负责在步骤之间导航和更新currentStep
变量。因此,每当currentStep
更新变量时,currentStepDiv 也应该更新以反映该变化。
存储和检索用户数据
改善表单用户体验的一个主要方法是将用户数据存储在浏览器中。多步骤表单通常很长,需要用户输入大量有关自己的信息。想象一下,用户填写了 95% 的表单,然后不小心按下F5键盘上的按钮,导致所有进度都丢失。这对用户来说是一种非常糟糕的体验。
使用localStorage
,我们可以在用户输入信息后立即存储信息,并在 DOM 内容加载后立即检索信息,这样用户就可以从上次中断的地方继续填写表单。要将此功能添加到表单中,我们可以在用户输入信息后立即保存信息。这可以使用input
事件来实现。
在添加input
事件监听器之前,从 DOM 中获取表单元素:
// Save data on each input event form.addEventListener("input", () => { const formData = { name: document.getElementById("name").value, email: document.getElementById("email").value, phone: document.getElementById("phone").value, company: document.getElementById("company").value, jobTitle: document.getElementById("jobTitle").value, yearsExperience: document.getElementById("yearsExperience").value, skills: document.getElementById("skills").value, highestDegree: document.getElementById("highestDegree").value, }; localStorage.setItem("formData", JSON.stringify(formData)); });
接下来,我们需要添加一些代码来帮助我们在 DOM 内容加载后检索用户数据。
window.addEventListener("DOMContentLoaded", () => { const savedData = JSON.parse(localStorage.getItem("formData")); if (savedData) { document.getElementById("name").value = savedData.name || ""; document.getElementById("email").value = savedData.email || ""; document.getElementById("phone").value = savedData.phone || ""; document.getElementById("company").value = savedData.company || ""; document.getElementById("jobTitle").value = savedData.jobTitle || ""; document.getElementById("yearsExperience").value = savedData.yearsExperience || ""; document.getElementById("skills").value = savedData.skills || ""; document.getElementById("highestDegree").value = savedData.highestDegree || ""; } });
localStorage
最后,一旦不再需要数据,最好立即删除它:
// Clear data on form submit form.addEventListener('submit', () => { // Clear localStorage once the form is submitted localStorage.removeItem('formData'); });
将当前步长值添加到localStorage
如果用户意外关闭了浏览器,他们应该能够返回到上次离开的位置。这意味着当前步骤值也必须保存在 中localStorage
。
要保存此值,请将以下行附加到showStep()
函数中:
localStorage.setItem("storedStep", currentStep);
现在我们可以检索当前步长值,并在 DOM 内容加载时将用户返回到他们上次离开的位置。将以下代码添加到DOMContentLoaded
处理程序以执行此操作:
const storedStep = localStorage.getItem("storedStep"); if (storedStep) { const storedStepInt = parseInt(storedStep); steps.forEach((el, index) => { el.hidden = index + 1 !== storedStepInt; }); currentStep = storedStepInt; currentStepDiv.innerText = currentStep; }
另外,不要忘记在localStorage
提交表单时清除当前的步长值。
localStorage.removeItem("storedStep");
上面这一行应该添加到提交处理程序中。
总结
创建多步骤表单有助于改善复杂数据输入的用户体验。通过仔细规划步骤、在每个步骤实施表单验证以及将用户数据暂时存储在浏览器中,您可以让用户更轻松地填写长表单。
网友评论文明上网理性发言 已有0人参与
发表评论: