You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现带必填字段校验的Tab页切换拦截功能

Tab页切换拦截与必填字段校验实现方案

需求回顾

  • 当前Tab页存在未填写的必填字段时,禁止切换到下一个Tab页
  • 为每个未填写的input显示提示信息“the field is required”
  • 未完成当前页所有必填字段时,Next按钮处于禁用状态
  • 最后一个输入框填写完成(通过onblur事件触发)后,启用Next按钮

修改方案与代码实现

1. HTML结构调整

修正重复id问题(id需唯一),为每个必填输入框添加错误提示容器:

<div class="container">
  <ul class="nav">
    <li class="active">1</li>
    <li>2</li>
    <li>3</li>
  </ul>

  <section class="section section-one active">
    <div class="input-group">
      <input type="text" id="name1" name="name" required minlength="4" maxlength="8" size="10">
      <span class="error-message"></span>
    </div>
    <div class="input-group">
      <input type="text" id="name2" name="name" required minlength="4" maxlength="8" size="10">
      <span class="error-message"></span>
    </div>
    <div class="input-group">
      <input type="text" id="name3" name="name" required minlength="4" maxlength="8" size="10">
      <span class="error-message"></span>
    </div>
    <div class="input-group">
      <input type="text" id="name4" name="name" required minlength="4" maxlength="8" size="10">
      <span class="error-message"></span>
    </div>
  </section>
  <section class="section section-two">
    <div class="input-group">
      <input type="text" id="name5" name="name" required minlength="4" maxlength="8" size="10">
      <span class="error-message"></span>
    </div>
    <div class="input-group">
      <input type="text" id="name6" name="name" required minlength="4" maxlength="8" size="10">
      <span class="error-message"></span>
    </div>
  </section>
  <section class="section section-three">
    <h2>section 3</h2>
  </section>

  <button class="previous disable" id="prevBtn" onclick="tabbedContent.goPrev()">Previous</button>
  <button class="next" id="nextBtn" onclick="tabbedContent.goNext()">Next</button>
</div>

2. CSS样式补充

添加错误提示信息的样式:

.container {
  max-width: 600px;
  margin: 0 auto;
  text-align: center;
}

.section {
  display: none;
}

.section.active {
  display: block;
}

ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
}

ul li {
  background: #ccc;
  padding: 10px 15px;
  margin-left: 6px;
  border-radius: 50%;
  cursor: pointer;
  opacity: .5;
}

ul li.active {
  opacity: 1 !important;
}

.next,
.previous {
  padding: 15px 10px;
  border-radius: 6px;
  background: deepskyblue;
  color: white;
  border: 0;
  outline: none;
  cursor: pointer;
  width: 100px;
}

.next.disable,
.previous.disable {
  cursor: not-allowed;
  opacity: .5;
}

.input-group {
  margin: 10px 0;
}

.error-message {
  display: block;
  color: #dc3545;
  font-size: 12px;
  margin-top: 4px;
}

3. JavaScript逻辑改造

新增校验方法、事件监听,修改切换拦截逻辑:

class TabbedContent {
  constructor() {
    this.tabs = document.querySelectorAll(".nav li");
    this.sections = document.querySelectorAll(".section");
    this.nextButton = document.querySelector("#nextBtn");
    this.prevButton = document.querySelector("#prevBtn");
    this.current = 0;
    this.init();
  }

  init() {
    this.addInputEventListeners();
    this.validateCurrentSection();
  }

  addInputEventListeners() {
    document.querySelectorAll('input[required]').forEach(input => {
      input.addEventListener('blur', () => {
        this.validateInput(input);
        this.validateCurrentSection();
      });
    });
  }

  validateInput(input) {
    const errorElement = input.nextElementSibling;
    if (!input.validity.valid) {
      if (input.validity.valueMissing) {
        errorElement.textContent = "the field is required";
      } else if (input.validity.tooShort) {
        errorElement.textContent = `Minimum length is ${input.minLength}`;
      } else if (input.validity.tooLong) {
        errorElement.textContent = `Maximum length is ${input.maxLength}`;
      }
    } else {
      errorElement.textContent = "";
    }
  }

  validateCurrentSection() {
    const currentSection = this.sections[this.current];
    const requiredInputs = currentSection.querySelectorAll('input[required]');
    let allValid = true;

    requiredInputs.forEach(input => {
      this.validateInput(input);
      if (!input.validity.valid) {
        allValid = false;
      }
    });

    if (this.current === this.tabs.length - 1) {
      this.nextButton.classList.remove("disable");
    } else {
      const method = allValid ? 'remove' : 'add';
      this.nextButton.classList[method]("disable");
    }
  }

  toggleTabs() {
    this.tabs.forEach(tab => tab.classList.remove('active'));
    this.tabs[this.current].classList.add("active");
  }

  toggleSections() {
    this.sections.forEach(section => section.classList.remove('active'));
    this.sections[this.current].classList.add("active");
  }

  togglePrev() {
    const method = this.current === 0 ? 'add' : 'remove';
    this.prevButton.classList[method]("disable");
  }

  toggleNext() {
    if (this.current === this.tabs.length - 1) {
      this.nextButton.classList.add("disable");
    }
  }

  goNext() {
    if (this.current < this.tabs.length - 1) {
      const currentSection = this.sections[this.current];
      const requiredInputs = currentSection.querySelectorAll('input[required]');
      let allValid = true;

      requiredInputs.forEach(input => {
        if (!input.validity.valid) {
          allValid = false;
        }
      });

      if (allValid) {
        this.current++;
        this.toggleTabs();
        this.toggleSections();
        this.toggleNext();
        this.togglePrev();
        this.validateCurrentSection();
      }
    }
  }

  goPrev() {
    if (this.current > 0) {
      this.current--;
      this.toggleTabs();
      this.toggleSections();
      this.toggleNext();
      this.togglePrev();
      this.validateCurrentSection();
    }
  }
}

const tabbedContent = new TabbedContent();

关键实现说明

  • 输入合法性校验:利用原生validityAPI判断输入状态,针对空值、长度不符等场景显示对应提示
  • 实时状态同步:每个必填输入框失去焦点时触发校验,自动更新Next按钮的禁用/启用状态
  • 切换拦截逻辑:点击Next按钮时先校验当前Tab所有必填字段,仅全部合法时才允许切换
  • Tab切换后校验:切换到新Tab后自动校验该页字段,确保按钮状态与当前页输入情况匹配

内容的提问来源于stack exchange,提问作者FelipeDeveloper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 13:24:56