jQuery提供了一系列方法来选择和操作表单元素。
jQuery提供了专门的表单选择器:
// 基本表单元素选择器
$(":input") // 选择所有input、textarea、select和button元素
$(":text") // 选择所有type="text"的input元素
$(":password") // 选择所有type="password"的input元素
$(":radio") // 选择所有单选框
$(":checkbox") // 选择所有复选框
$(":submit") // 选择所有提交按钮
$(":reset") // 选择所有重置按钮
$(":button") // 选择所有按钮
$(":image") // 选择所有图片按钮
$(":file") // 选择所有文件上传控件
$(":hidden") // 选择所有隐藏元素(包括type="hidden")
$(":selected") // 选择所有选中的option元素
$(":checked") // 选择所有选中的复选框和单选框
$(":enabled") // 选择所有启用的元素
$(":disabled") // 选择所有禁用的元素
$(":focus") // 选择当前聚焦的元素
// 组合使用
$("form :input") // 选择表单内所有输入元素
$("form :text:enabled") // 选择表单内所有启用的文本框
$("#myForm input[type='text']") // 选择指定类型的输入框
$("input[name='username']") // 根据name属性选择
$("input:not(:disabled)") // 选择没有禁用的输入框
// 实用示例
// 选择所有必填字段
$("input[required], select[required], textarea[required]")
// 选择可见的表单元素
$(":input:visible")
// 选择特定表单内的元素
$("#loginForm :input")
// 选择第一个表单元素
$("form:first :input:first")
// 选择最后一个表单元素
$("form:last :input:last")
// 获取文本框值
const username = $("#username").val(); // 获取值
$("#username").val("新用户名"); // 设置值
// 获取和设置密码框
const password = $("#password").val();
$("#password").val("新密码");
// 获取和设置文本区域
const message = $("#message").val();
$("#message").val("新的消息内容");
// 获取和设置下拉框
const city = $("#city").val(); // 获取选中的值
$("#city").val("sh"); // 设置选中值
// 获取和设置单选按钮
const gender = $("input[name='gender']:checked").val(); // 获取选中的值
$("input[name='gender'][value='male']").prop("checked", true); // 设置选中
// 获取和设置复选框
// 单个复选框
const isAgree = $("#agree").prop("checked"); // 获取是否选中
$("#agree").prop("checked", true); // 设置选中
// 多个复选框 - 获取选中的值
const hobbies = [];
$("input[name='hobbies']:checked").each(function() {
hobbies.push($(this).val());
});
// 多个复选框 - 设置选中
$("input[name='hobbies'][value='reading']").prop("checked", true);
$("input[name='hobbies'][value='music']").prop("checked", true);
// 批量设置表单值
function setFormValues(data) {
$.each(data, function(key, value) {
const $element = $(`[name="${key}"]`);
if($element.is(":checkbox")) {
// 处理复选框
if(Array.isArray(value)) {
$element.prop("checked", false);
value.forEach(val => {
$(`[name="${key}"][value="${val}"]`).prop("checked", true);
});
}
} else if($element.is(":radio")) {
// 处理单选按钮
$(`[name="${key}"][value="${value}"]`).prop("checked", true);
} else if($element.is("select")) {
// 处理下拉框
$element.val(value);
} else {
// 处理文本框等
$element.val(value);
}
});
}
// 示例:设置用户数据
const userData = {
username: "张三",
email: "zhangsan@example.com",
gender: "male",
city: "sh",
hobbies: ["reading", "sports"]
};
setFormValues(userData);
// 批量获取表单值
function getFormValues(selector) {
const data = {};
$(selector).find(":input").each(function() {
const $this = $(this);
const name = $this.attr("name");
if(!name) return;
if($this.is(":checkbox")) {
// 复选框:存储为数组
if(!data[name]) data[name] = [];
if($this.is(":checked")) {
data[name].push($this.val());
}
} else if($this.is(":radio")) {
// 单选按钮:只有选中的才存储
if($this.is(":checked")) {
data[name] = $this.val();
}
} else if($this.is("select[multiple]")) {
// 多选下拉框
data[name] = $this.val() || [];
} else {
// 其他输入框
data[name] = $this.val();
}
});
return data;
}
// 使用示例
const formData = getFormValues("#userForm");
console.log(formData);
// 基本序列化
const serialized = $("#myForm").serialize();
// 结果: "username=张三&email=zhangsan%40example.com&city=sh"
// 序列化为数组
const serializedArray = $("#myForm").serializeArray();
// 结果: [
// {name: "username", value: "张三"},
// {name: "email", value: "zhangsan@example.com"},
// {name: "city", value: "sh"}
// ]
// 转换为对象
function serializeObject(formSelector) {
const array = $(formSelector).serializeArray();
const obj = {};
$.each(array, function() {
if(obj[this.name] !== undefined) {
if(!Array.isArray(obj[this.name])) {
obj[this.name] = [obj[this.name]];
}
obj[this.name].push(this.value);
} else {
obj[this.name] = this.value;
}
});
return obj;
}
// 包含文件上传的序列化
// 注意:serialize()不包含文件输入,需要使用FormData
const formData = new FormData($("#myForm")[0]);
// 手动构建FormData
function buildFormData(formSelector) {
const formData = new FormData();
const $form = $(formSelector);
// 添加普通字段
$form.find(":input").not(":file").each(function() {
const $this = $(this);
const name = $this.attr("name");
if(!name) return;
if($this.is(":checkbox") || $this.is(":radio")) {
if($this.is(":checked")) {
formData.append(name, $this.val());
}
} else if($this.is("select[multiple]")) {
const values = $this.val() || [];
values.forEach(value => {
formData.append(name, value);
});
} else {
formData.append(name, $this.val());
}
});
// 添加文件
$form.find("input[type='file']").each(function() {
const $this = $(this);
const name = $this.attr("name");
const files = $this[0].files;
if(files.length > 0) {
for(let i = 0; i < files.length; i++) {
formData.append(name, files[i]);
}
}
});
return formData;
}
// 序列化特定字段
function serializeSelectedFields(fieldSelectors) {
const data = {};
$(fieldSelectors).each(function() {
const $this = $(this);
const name = $this.attr("name");
if(!name) return;
if($this.is(":checkbox") || $this.is(":radio")) {
if($this.is(":checked")) {
data[name] = $this.val();
}
} else if($this.is("select[multiple]")) {
data[name] = $this.val() || [];
} else {
data[name] = $this.val();
}
});
return data;
}
表单事件处理是表单交互的核心,jQuery提供了丰富的事件处理方法。
// focus - 获取焦点时触发
$("#username").focus(function() {
$(this).css("border-color", "#4CAF50");
$(this).next(".hint").show();
});
// blur - 失去焦点时触发
$("#username").blur(function() {
$(this).css("border-color", "#ccc");
validateUsername($(this).val());
});
// 自动聚焦第一个字段
$(document).ready(function() {
$("form:first :input:visible:enabled:first").focus();
});
// 回车键跳转到下一个字段
$(".tab-input").keydown(function(e) {
if(e.keyCode === 13) { // 回车键
e.preventDefault();
const inputs = $(".tab-input");
const index = inputs.index(this) + 1;
if(index < inputs.length) {
inputs.eq(index).focus();
}
}
});
// 自定义焦点样式
$(":input").focus(function() {
$(this).addClass("focus-highlight");
}).blur(function() {
$(this).removeClass("focus-highlight");
});
// 实时显示焦点状态
$(":input").on("focus blur", function(e) {
const status = e.type === "focus" ? "获得焦点" : "失去焦点";
console.log($(this).attr("name") + " " + status);
});
// input - 输入时实时触发
$("#search").on("input", function() {
const query = $(this).val();
searchSuggestions(query);
});
// change - 值改变且失去焦点后触发
$("#country").change(function() {
const country = $(this).val();
loadCities(country);
});
// keydown/keyup - 键盘事件
$("#message").keydown(function(e) {
// 限制最大长度
const maxLength = 500;
const currentLength = $(this).val().length;
if(currentLength >= maxLength && e.keyCode !== 8 && e.keyCode !== 46) {
e.preventDefault(); // 阻止输入
showMessage("已达到最大长度限制");
}
}).keyup(function() {
// 实时统计字数
const length = $(this).val().length;
$("#char-count").text(length);
});
// 实时验证邮箱格式
$("#email").on("input", function() {
const email = $(this).val();
const isValid = validateEmail(email);
if(email && !isValid) {
$(this).addClass("is-invalid");
$("#email-error").text("邮箱格式不正确");
} else {
$(this).removeClass("is-invalid");
$("#email-error").text("");
}
});
// 密码强度实时检查
$("#password").on("input", function() {
const password = $(this).val();
const strength = checkPasswordStrength(password);
updatePasswordStrengthIndicator(strength);
});
// 价格计算实时更新
$("#quantity, #price").on("input", function() {
const quantity = parseInt($("#quantity").val()) || 0;
const price = parseFloat($("#price").val()) || 0;
const total = quantity * price;
$("#total").val(total.toFixed(2));
});
// 表单字段联动
$("#province").change(function() {
const provinceId = $(this).val();
if(provinceId) {
loadCities(provinceId);
} else {
$("#city").empty().append('');
}
});
$("#city").change(function() {
const cityId = $(this).val();
if(cityId) {
loadDistricts(cityId);
}
});
// submit - 表单提交时触发
$("#myForm").submit(function(e) {
e.preventDefault(); // 阻止默认提交行为
// 表单验证
if(!validateForm()) {
return false;
}
// 获取表单数据
const formData = $(this).serialize();
// 显示加载状态
showLoading();
// 提交表单
$.post($(this).attr("action"), formData)
.done(function(response) {
if(response.success) {
showSuccess("提交成功!");
resetForm();
} else {
showError(response.message);
}
})
.fail(function() {
showError("提交失败,请重试");
})
.always(function() {
hideLoading();
});
});
// 阻止表单提交(条件性)
$("#orderForm").submit(function(e) {
if(!confirm("确认提交订单吗?")) {
e.preventDefault();
return false;
}
});
// 提交前验证
$("#registerForm").submit(function(e) {
const errors = [];
// 验证用户名
if(!$("#username").val()) {
errors.push("用户名不能为空");
}
// 验证邮箱
if(!validateEmail($("#email").val())) {
errors.push("邮箱格式不正确");
}
// 验证密码
if($("#password").val().length < 6) {
errors.push("密码至少6位");
}
// 如果有错误
if(errors.length > 0) {
e.preventDefault();
showErrors(errors);
return false;
}
});
// 多个提交按钮处理
$("#saveDraft").click(function() {
$("#action").val("draft");
$("#articleForm").submit();
});
$("#publish").click(function() {
$("#action").val("publish");
$("#articleForm").submit();
});
// 防止重复提交
let isSubmitting = false;
$("#myForm").submit(function(e) {
if(isSubmitting) {
e.preventDefault();
return false;
}
isSubmitting = true;
$("#submitBtn").prop("disabled", true).text("提交中...");
// 3秒后自动重置提交状态(防止请求失败导致按钮一直禁用)
setTimeout(function() {
isSubmitting = false;
$("#submitBtn").prop("disabled", false).text("提交");
}, 3000);
});
// 文件上传表单提交
$("#uploadForm").submit(function(e) {
e.preventDefault();
const formData = new FormData(this);
$.ajax({
url: $(this).attr("action"),
type: "POST",
data: formData,
processData: false,
contentType: false,
xhr: function() {
const xhr = new XMLHttpRequest();
// 上传进度
xhr.upload.addEventListener("progress", function(e) {
if(e.lengthComputable) {
const percent = (e.loaded / e.total) * 100;
$("#progress").width(percent + "%");
}
});
return xhr;
},
success: function(response) {
showSuccess("上传成功!");
}
});
});
// reset - 表单重置时触发
$("#myForm").on("reset", function() {
if(!confirm("确定要重置表单吗?所有输入的数据都将丢失。")) {
return false;
}
// 重置后执行其他操作
clearValidationErrors();
resetCustomFields();
});
// 手动重置表单
$("#resetBtn").click(function() {
if(confirm("确定要重置表单吗?")) {
$("#myForm")[0].reset(); // 原生方法
// 或
$("#myForm").trigger("reset");
}
});
// 自定义重置逻辑
function customReset(formSelector) {
const $form = $(formSelector);
// 清空所有输入框
$form.find(":input").each(function() {
const $this = $(this);
if($this.is(":checkbox, :radio")) {
$this.prop("checked", false);
} else if($this.is("select")) {
$this.prop("selectedIndex", 0);
} else {
$this.val("");
}
});
// 清除验证状态
$form.find(".is-invalid").removeClass("is-invalid");
$form.find(".error-message").remove();
// 重置自定义组件
resetCustomComponents();
// 聚焦第一个字段
$form.find(":input:visible:enabled:first").focus();
}
// 取消按钮处理
$("#cancelBtn").click(function() {
if(hasUnsavedChanges()) {
if(!confirm("有未保存的更改,确定要取消吗?")) {
return false;
}
}
// 返回上一页或关闭窗口
if(window.history.length > 1) {
window.history.back();
} else {
window.location.href = "/dashboard";
}
});
// 自动保存草稿
let saveTimer;
function startAutoSave() {
saveTimer = setInterval(function() {
if(hasChanges()) {
saveDraft();
}
}, 30000); // 每30秒自动保存
}
// 离开页面前提示保存
$(window).on("beforeunload", function() {
if(hasUnsavedChanges()) {
return "有未保存的更改,确定要离开吗?";
}
});
// 防止误操作离开
function preventAccidentalLeave() {
let hasChanges = false;
$("#myForm :input").on("input change", function() {
hasChanges = true;
});
$("#saveBtn").click(function() {
hasChanges = false;
});
$(window).on("beforeunload", function() {
if(hasChanges) {
return "您有未保存的更改,确定要离开吗?";
}
});
}
表单验证是确保数据正确性的重要环节,jQuery提供了灵活的验证方案。
// 验证是否为空
function isEmpty(value) {
return !value || value.trim() === "";
}
// 验证邮箱格式
function validateEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email);
}
// 验证手机号
function validatePhone(phone) {
const re = /^1[3-9]\d{9}$/; // 中国手机号
return re.test(phone);
}
// 验证身份证号
function validateIDCard(idCard) {
const re = /(^\d{15}$)|(^\d{17}(\d|X|x)$)/;
return re.test(idCard);
}
// 验证URL
function validateURL(url) {
const re = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/;
return re.test(url);
}
// 验证密码强度
function validatePassword(password) {
// 至少8位,包含大小写字母和数字
const re = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;
return re.test(password);
}
// 验证用户名
function validateUsername(username) {
// 3-20位字母、数字或下划线
const re = /^[a-zA-Z0-9_]{3,20}$/;
return re.test(username);
}
// 验证数字范围
function validateNumberRange(value, min, max) {
const num = parseFloat(value);
return !isNaN(num) && num >= min && num <= max;
}
// 验证字符串长度
function validateLength(value, min, max) {
const length = value.length;
return length >= min && length <= max;
}
// 用户名实时验证
$("#username").on("input", function() {
const username = $(this).val();
const $feedback = $(this).next(".invalid-feedback");
if(isEmpty(username)) {
showError($(this), "用户名不能为空");
} else if(!validateUsername(username)) {
showError($(this), "用户名必须是3-20位字母、数字或下划线");
} else {
showSuccess($(this));
// 检查用户名是否已存在
checkUsernameAvailability(username);
}
});
// 邮箱实时验证
$("#email").on("input", debounce(function() {
const email = $(this).val();
if(isEmpty(email)) {
showError($(this), "邮箱不能为空");
} else if(!validateEmail(email)) {
showError($(this), "邮箱格式不正确");
} else {
showSuccess($(this));
}
}, 500));
// 密码强度实时显示
$("#password").on("input", function() {
const password = $(this).val();
const strength = checkPasswordStrength(password);
updateStrengthIndicator(strength);
});
function checkPasswordStrength(password) {
let strength = 0;
// 长度至少8位
if(password.length >= 8) strength++;
// 包含小写字母
if(/[a-z]/.test(password)) strength++;
// 包含大写字母
if(/[A-Z]/.test(password)) strength++;
// 包含数字
if(/\d/.test(password)) strength++;
// 包含特殊字符
if(/[^a-zA-Z0-9]/.test(password)) strength++;
return strength;
}
function updateStrengthIndicator(strength) {
const $indicator = $("#password-strength");
const $text = $("#password-strength-text");
$indicator.removeClass().addClass("strength-" + strength);
const texts = ["非常弱", "弱", "一般", "强", "非常强"];
$text.text(texts[strength] || "");
}
// 确认密码实时验证
$("#confirm-password").on("input", function() {
const password = $("#password").val();
const confirmPassword = $(this).val();
if(isEmpty(confirmPassword)) {
showError($(this), "请确认密码");
} else if(password !== confirmPassword) {
showError($(this), "两次输入的密码不一致");
} else {
showSuccess($(this));
}
});
// 显示验证状态
function showError($element, message) {
$element.addClass("is-invalid");
let $feedback = $element.next(".invalid-feedback");
if(!$feedback.length) {
$feedback = $('');
$element.after($feedback);
}
$feedback.text(message);
}
function showSuccess($element) {
$element.removeClass("is-invalid");
$element.addClass("is-valid");
}
// 表单验证器类
class FormValidator {
constructor(formSelector) {
this.$form = $(formSelector);
this.rules = {};
this.messages = {};
this.errors = [];
this.init();
}
init() {
// 收集验证规则
this.collectRules();
// 绑定事件
this.bindEvents();
}
collectRules() {
this.$form.find("[data-validate]").each((index, element) => {
const $element = $(element);
const name = $element.attr("name");
const rules = $element.data("validate").split("|");
this.rules[name] = rules;
this.messages[name] = {};
rules.forEach(rule => {
const message = $element.data(`${rule}-msg`);
if(message) {
this.messages[name][rule] = message;
}
});
});
}
bindEvents() {
// 实时验证
this.$form.on("input", "[data-validate]", (e) => {
this.validateField($(e.target));
});
// 提交验证
this.$form.on("submit", (e) => {
if(!this.validateAll()) {
e.preventDefault();
this.displayErrors();
}
});
}
validateField($element) {
const name = $element.attr("name");
const value = $element.val();
const rules = this.rules[name] || [];
let isValid = true;
rules.forEach(rule => {
if(!this.validateRule(rule, value, $element)) {
isValid = false;
this.showFieldError($element, rule);
} else {
this.clearFieldError($element);
}
});
return isValid;
}
validateRule(rule, value, $element) {
switch(rule) {
case "required":
return !this.isEmpty(value);
case "email":
return this.validateEmail(value);
case "phone":
return this.validatePhone(value);
case "min":
const min = $element.data("min");
return value.length >= min;
case "max":
const max = $element.data("max");
return value.length <= max;
case "confirmed":
const confirmField = $element.data("confirm");
const confirmValue = $(`[name="${confirmField}"]`).val();
return value === confirmValue;
default:
return true;
}
}
validateAll() {
this.errors = [];
let isValid = true;
Object.keys(this.rules).forEach(name => {
const $element = $(`[name="${name}"]`);
if(!this.validateField($element)) {
isValid = false;
this.errors.push({
field: name,
element: $element,
message: this.getErrorMessage(name)
});
}
});
return isValid;
}
displayErrors() {
// 清空之前的错误
$(".validation-error").remove();
// 显示所有错误
if(this.errors.length > 0) {
let errorHtml = '';
errorHtml += '请修正以下错误:
';
this.errors.forEach(error => {
errorHtml += `- ${error.message}
`;
error.element.addClass("is-invalid");
});
errorHtml += '
';
this.$form.prepend(errorHtml);
this.errors[0].element.focus();
}
}
// 辅助方法
isEmpty(value) {
return !value || value.trim() === "";
}
validateEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email);
}
validatePhone(phone) {
const re = /^1[3-9]\d{9}$/;
return re.test(phone);
}
getErrorMessage(fieldName) {
const fieldMessages = this.messages[fieldName] || {};
return fieldMessages.required || "请填写此字段";
}
showFieldError($element, rule) {
const message = this.getFieldErrorMessage($element, rule);
$element.addClass("is-invalid");
let $feedback = $element.next(".invalid-feedback");
if(!$feedback.length) {
$feedback = $('');
$element.after($feedback);
}
$feedback.text(message);
}
clearFieldError($element) {
$element.removeClass("is-invalid").addClass("is-valid");
$element.next(".invalid-feedback").remove();
}
getFieldErrorMessage($element, rule) {
const customMessage = $element.data(`${rule}-msg`);
if(customMessage) return customMessage;
const defaultMessages = {
required: "此字段为必填项",
email: "请输入有效的邮箱地址",
phone: "请输入有效的手机号",
min: "长度不能小于${min}个字符",
max: "长度不能超过${max}个字符",
confirmed: "两次输入不一致"
};
let message = defaultMessages[rule] || "验证失败";
// 替换占位符
if(rule === "min" || rule === "max") {
const value = $element.data(rule);
message = message.replace(`\${${rule}}`, value);
}
return message;
}
}
// 使用验证器
const validator = new FormValidator("#myForm");
// HTML示例
表单提交是表单处理的最终环节,jQuery提供了灵活的提交方式。
// 传统表单提交(同步)
$("#traditional-form").submit(function(e) {
// 表单验证
if(!validateForm(this)) {
e.preventDefault();
return false;
}
// 提交前确认
if(!confirm("确定要提交吗?")) {
e.preventDefault();
return false;
}
// 显示提交状态
$("#submit-btn").prop("disabled", true).text("提交中...");
// 表单会自动提交到action指定的地址
});
// 手动提交表单
$("#manual-submit").click(function() {
// 方式1:触发submit事件
$("#myForm").submit();
// 方式2:使用原生submit方法(不会触发submit事件)
// $("#myForm")[0].submit();
});
// 多按钮表单提交
$("#save-btn").click(function() {
// 设置隐藏字段标识操作类型
$("#action-type").val("save");
$("#myForm").submit();
});
$("#submit-btn").click(function() {
$("#action-type").val("submit");
$("#myForm").submit();
});
$("#delete-btn").click(function() {
if(confirm("确定要删除吗?")) {
$("#action-type").val("delete");
$("#myForm").submit();
}
});
// 表单提交前的处理
$("#order-form").submit(function(e) {
// 计算总价
const quantity = parseInt($("#quantity").val()) || 0;
const price = parseFloat($("#price").val()) || 0;
const total = quantity * price;
// 设置隐藏字段
$("#total-price").val(total.toFixed(2));
// 格式化数据
const now = new Date();
$("#submit-time").val(now.toISOString());
// 添加用户代理信息
$("#user-agent").val(navigator.userAgent);
// 继续提交
return true;
});
// 基本AJAX表单提交
$("#ajax-form").submit(function(e) {
e.preventDefault();
// 获取表单数据
const formData = $(this).serialize();
// 显示加载状态
showLoading();
// 发送AJAX请求
$.ajax({
url: $(this).attr("action"),
type: "POST",
data: formData,
dataType: "json",
success: function(response) {
handleSuccess(response);
},
error: function(xhr, status, error) {
handleError(xhr);
},
complete: function() {
hideLoading();
}
});
});
// 使用FormData(支持文件上传)
$("#upload-form").submit(function(e) {
e.preventDefault();
const formData = new FormData(this);
$.ajax({
url: $(this).attr("action"),
type: "POST",
data: formData,
processData: false,
contentType: false,
xhr: function() {
const xhr = new XMLHttpRequest();
// 上传进度
xhr.upload.addEventListener("progress", function(e) {
if(e.lengthComputable) {
const percent = Math.round((e.loaded / e.total) * 100);
updateProgress(percent);
}
});
return xhr;
},
success: function(response) {
showSuccess("上传成功!");
},
error: function() {
showError("上传失败,请重试");
}
});
});
// 批量提交多个表单
function submitMultipleForms(formSelectors) {
const promises = [];
formSelectors.forEach(selector => {
const promise = submitForm(selector);
promises.push(promise);
});
// 等待所有表单提交完成
$.when.apply($, promises)
.done(function() {
showSuccess("所有表单提交成功!");
})
.fail(function() {
showError("部分表单提交失败");
});
}
function submitForm(selector) {
return $.ajax({
url: $(selector).attr("action"),
type: "POST",
data: $(selector).serialize()
});
}
// 重试机制
class FormSubmitter {
constructor(formSelector, options = {}) {
this.$form = $(formSelector);
this.options = $.extend({
maxRetries: 3,
retryDelay: 1000,
timeout: 30000
}, options);
this.retryCount = 0;
this.init();
}
init() {
this.$form.on("submit", this.handleSubmit.bind(this));
}
handleSubmit(e) {
e.preventDefault();
if(this.isSubmitting) {
return false;
}
this.isSubmitting = true;
this.retryCount = 0;
this.submit();
return false;
}
submit() {
const formData = this.$form.serialize();
$.ajax({
url: this.$form.attr("action"),
type: "POST",
data: formData,
timeout: this.options.timeout,
success: this.handleSuccess.bind(this),
error: this.handleError.bind(this)
});
}
handleSuccess(response) {
this.isSubmitting = false;
if(response.success) {
this.showSuccess(response.message);
this.$form[0].reset();
} else {
this.showError(response.message || "提交失败");
}
}
handleError(xhr, status, error) {
this.retryCount++;
if(this.retryCount <= this.options.maxRetries) {
this.showRetryMessage();
setTimeout(this.submit.bind(this), this.options.retryDelay);
} else {
this.isSubmitting = false;
this.showError("提交失败,请检查网络连接后重试");
}
}
showRetryMessage() {
const message = `提交失败,正在重试... (${this.retryCount}/${this.options.maxRetries})`;
this.updateStatus(message, "warning");
}
showSuccess(message) {
this.updateStatus(message, "success");
}
showError(message) {
this.updateStatus(message, "danger");
}
updateStatus(message, type) {
const $status = this.$form.find(".submit-status");
const alertClass = `alert alert-${type}`;
if(!$status.length) {
$status = $('');
this.$form.append($status);
}
$status.html(`${message}`);
}
}
// 使用重试提交器
const submitter = new FormSubmitter("#myForm", {
maxRetries: 3,
retryDelay: 2000,
timeout: 10000
});
// 防止重复提交
function preventDuplicateSubmit(formSelector) {
let isSubmitting = false;
$(formSelector).submit(function(e) {
if(isSubmitting) {
e.preventDefault();
return false;
}
isSubmitting = true;
// 禁用提交按钮
$(this).find(":submit").prop("disabled", true);
// 显示提交状态
showSubmittingState();
// 超时自动重置(防止请求失败导致按钮一直禁用)
setTimeout(function() {
isSubmitting = false;
$(formSelector).find(":submit").prop("disabled", false);
hideSubmittingState();
}, 10000); // 10秒后重置
return true;
});
}
// 提交队列
class SubmitQueue {
constructor() {
this.queue = [];
this.processing = false;
}
add(formData, callback) {
this.queue.push({ formData, callback });
if(!this.processing) {
this.process();
}
}
process() {
if(this.queue.length === 0) {
this.processing = false;
return;
}
this.processing = true;
const { formData, callback } = this.queue.shift();
$.ajax({
url: "/api/submit",
type: "POST",
data: formData,
success: (response) => {
if(callback) callback(null, response);
this.process();
},
error: (xhr) => {
if(callback) callback(xhr);
this.process();
}
});
}
}
// 使用提交队列
const submitQueue = new SubmitQueue();
$("#myForm").submit(function(e) {
e.preventDefault();
const formData = $(this).serialize();
submitQueue.add(formData, function(error, response) {
if(error) {
showError("提交失败");
} else {
showSuccess("提交成功");
}
});
});
// 提交节流
function createThrottledSubmit(selector, delay = 1000) {
let lastSubmitTime = 0;
let timer = null;
$(selector).submit(function(e) {
e.preventDefault();
const now = Date.now();
if(now - lastSubmitTime < delay) {
// 如果距离上次提交时间太短,延迟执行
clearTimeout(timer);
timer = setTimeout(() => {
doSubmit(this);
lastSubmitTime = Date.now();
}, delay - (now - lastSubmitTime));
return false;
}
doSubmit(this);
lastSubmitTime = now;
return false;
});
function doSubmit(form) {
const formData = $(form).serialize();
$.ajax({
url: $(form).attr("action"),
type: "POST",
data: formData,
success: function(response) {
// 处理成功响应
}
});
}
}
// 离线提交支持
class OfflineSubmit {
constructor(formSelector, storageKey = "pending_submissions") {
this.$form = $(formSelector);
this.storageKey = storageKey;
this.pendingSubmissions = this.loadPendingSubmissions();
this.init();
}
init() {
// 监听在线状态
window.addEventListener("online", this.handleOnline.bind(this));
// 表单提交处理
this.$form.submit(this.handleSubmit.bind(this));
}
handleSubmit(e) {
e.preventDefault();
const formData = this.$form.serialize();
if(navigator.onLine) {
// 在线状态直接提交
this.submitOnline(formData);
} else {
// 离线状态保存到本地
this.saveOffline(formData);
}
}
submitOnline(formData) {
$.ajax({
url: this.$form.attr("action"),
type: "POST",
data: formData,
success: (response) => {
if(response.success) {
this.showSuccess("提交成功");
this.$form[0].reset();
}
}
});
}
saveOffline(formData) {
const submission = {
data: formData,
timestamp: new Date().getTime(),
url: this.$form.attr("action")
};
this.pendingSubmissions.push(submission);
this.savePendingSubmissions();
this.showInfo("网络离线,提交已保存到本地。连接网络后将自动提交。");
this.$form[0].reset();
}
handleOnline() {
if(this.pendingSubmissions.length > 0) {
this.processPendingSubmissions();
}
}
processPendingSubmissions() {
const successful = [];
// 逐个提交待处理的数据
const promises = this.pendingSubmissions.map((submission, index) => {
return $.ajax({
url: submission.url,
type: "POST",
data: submission.data
}).then(() => {
successful.push(index);
});
});
// 所有请求完成后,移除已成功的
$.when.apply($, promises).then(() => {
this.pendingSubmissions = this.pendingSubmissions.filter((_, index) => {
return !successful.includes(index);
});
this.savePendingSubmissions();
if(successful.length > 0) {
this.showSuccess(`${successful.length}条离线提交已同步`);
}
});
}
loadPendingSubmissions() {
const data = localStorage.getItem(this.storageKey);
return data ? JSON.parse(data) : [];
}
savePendingSubmissions() {
localStorage.setItem(this.storageKey, JSON.stringify(this.pendingSubmissions));
}
}
// 使用离线提交
const offlineSubmit = new OfflineSubmit("#myForm");
使用jQuery表单插件可以快速实现复杂功能,提高开发效率。
| 插件名称 | 功能描述 | 引入方式 |
|---|---|---|
| jQuery Validation | 表单验证插件,功能强大,支持自定义规则 | <script src="jquery.validate.js"></script> |
| Bootstrap Validator | 基于Bootstrap的表单验证插件 | <script src="bootstrap-validator.js"></script> |
| Select2 | 增强的下拉选择框,支持搜索、多选等功能 | <script src="select2.min.js"></script> |
| jQuery Mask | 输入框掩码插件,用于格式化输入 | <script src="jquery.mask.min.js"></script> |
| jQuery Form | AJAX表单提交插件,支持文件上传 | <script src="jquery.form.js"></script> |
| Datepicker | 日期选择器插件 | <script src="bootstrap-datepicker.js"></script> |
// 引入jQuery Validation插件
// <script src="https://cdn.jsdelivr.net/npm/jquery-validation@1.19.5/dist/jquery.validate.min.js"></script>
// 基本使用
$("#myForm").validate({
rules: {
username: {
required: true,
minlength: 3,
maxlength: 20
},
email: {
required: true,
email: true
},
password: {
required: true,
minlength: 6
},
confirm_password: {
required: true,
equalTo: "#password"
}
},
messages: {
username: {
required: "请输入用户名",
minlength: "用户名至少3个字符",
maxlength: "用户名最多20个字符"
},
email: {
required: "请输入邮箱地址",
email: "请输入有效的邮箱地址"
},
password: {
required: "请输入密码",
minlength: "密码至少6位"
},
confirm_password: {
required: "请确认密码",
equalTo: "两次输入的密码不一致"
}
},
submitHandler: function(form) {
// 验证通过后执行
$.ajax({
url: $(form).attr("action"),
type: "POST",
data: $(form).serialize(),
success: function(response) {
if(response.success) {
alert("提交成功!");
form.reset();
}
}
});
},
errorPlacement: function(error, element) {
// 自定义错误信息位置
error.addClass("invalid-feedback");
element.addClass("is-invalid");
if(element.parent(".input-group").length) {
error.insertAfter(element.parent());
} else {
error.insertAfter(element);
}
},
highlight: function(element) {
// 高亮显示错误字段
$(element).addClass("is-invalid");
},
unhighlight: function(element) {
// 移除错误高亮
$(element).removeClass("is-invalid");
}
});
// 自定义验证规则
$.validator.addMethod("phoneCN", function(value, element) {
return this.optional(element) || /^1[3-9]\d{9}$/.test(value);
}, "请输入有效的手机号码");
$.validator.addMethod("chinese", function(value, element) {
return this.optional(element) || /^[\u4e00-\u9fa5]+$/.test(value);
}, "请输入中文");
// 使用自定义规则
$("#myForm").validate({
rules: {
mobile: {
required: true,
phoneCN: true
},
realname: {
required: true,
chinese: true
}
}
});
// 动态添加/移除验证规则
const validator = $("#myForm").validate();
validator.destroy(); // 销毁验证器
// 重新初始化
$("#myForm").validate({
rules: {
// 新规则
}
});
// 基本使用
$("#single-select").select2({
placeholder: "请选择",
allowClear: true
});
// 多选模式
$("#multi-select").select2({
placeholder: "请选择(可多选)",
allowClear: true,
multiple: true,
maximumSelectionLength: 3 // 最多选择3个
});
// 远程数据源
$("#remote-select").select2({
placeholder: "搜索并选择",
allowClear: true,
ajax: {
url: "/api/search",
dataType: "json",
delay: 250,
data: function(params) {
return {
q: params.term, // 搜索关键词
page: params.page || 1
};
},
processResults: function(data, params) {
params.page = params.page || 1;
return {
results: data.items,
pagination: {
more: (params.page * 10) < data.total_count
}
};
},
cache: true
},
minimumInputLength: 2 // 至少输入2个字符才开始搜索
});
// 模板定制
$("#custom-select").select2({
templateResult: formatResult,
templateSelection: formatSelection
});
function formatResult(item) {
if(!item.id) {
return item.text;
}
const $result = $(
'' +
'
' +
item.text +
'' + item.email + '' +
''
);
return $result;
}
function formatSelection(item) {
return item.text;
}
// 事件处理
$("#mySelect").on("select2:select", function(e) {
const data = e.params.data;
console.log("选择了:", data);
});
$("#mySelect").on("select2:open", function() {
console.log("下拉框打开了");
});
$("#mySelect").on("select2:close", function() {
console.log("下拉框关闭了");
});
// 动态更新选项
function updateSelectOptions() {
const newData = [
{id: 1, text: "选项1"},
{id: 2, text: "选项2"},
{id: 3, text: "选项3"}
];
$("#mySelect").empty().select2({
data: newData
});
}
// 获取和设置值
const selectedValues = $("#multi-select").val(); // 获取值
$("#multi-select").val(["1", "2"]).trigger("change"); // 设置值
| 方法/属性 | 描述 | 示例 |
|---|---|---|
.val() |
获取或设置表单元素的值 | $("#input").val() |
.serialize() |
序列化表单为查询字符串 | $("form").serialize() |
.serializeArray() |
序列化表单为数组 | $("form").serializeArray() |
.submit() |
提交表单或绑定提交事件 | $("form").submit() |
.reset() |
重置表单 | $("form")[0].reset() |
.focus() |
设置焦点或绑定焦点事件 | $("#input").focus() |
.blur() |
失去焦点或绑定失去焦点事件 | $("#input").blur() |
.change() |
值改变事件 | $("select").change() |
.prop('checked') |
获取或设置复选框/单选框状态 | $("#checkbox").prop('checked') |
:input |
表单元素选择器 | $("form :input") |
:checked |
选中状态选择器 | $("input:checked") |
:selected |
选中选项选择器 | $("option:selected") |
创建一个完整的订单表单系统,包含以下功能:
| 商品总额: | ¥0 |
| 包装费: | ¥0 |
| 优惠折扣: | -¥0 |
| 总计: | ¥0 |