ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

EasyUI登录页开发实战:表单校验与Ajax交互详解

EasyUI登录页开发实战:表单校验与Ajax交互详解 简介这是一套基于 EasyUI 的简单登录界面完整工程包面向刚接触 jQuery EasyUI 的前端初学者也适合需要快速搭建管理后台登录入口的 Java Web 开发者。解压后可见一个可导入 Eclipse 运行的后端工程包含登录页布局、表单提交、Servlet 处理示例以及 EasyUI 常见组件的核心样式与脚本通过阅读目录结构能理清页面、样式、图片素材和后台配置之间的关系。资源共 332 个文件其中 53 个 js、52 个 css 构成组件交互与主题外观50 个 html 提供页面示例另有大量 gif/png 图标素材和 java/class、工程配置类文件整体仅 482KB小巧但覆盖完整。目前已有 895 人浏览学习适合在本地跑起来后边看边改也能作为从静态页面过渡到完整 Web 应用的起点快速掌握登录页面从界面绘制、前端校验到后端处理的常见写法也很适合课程设计参考。1. 为什么都2025年了我还捡起EasyUI写登录页如果你长期混迹于前端社区大概会觉得EasyUI这个名字已经属于上个时代。React、Vue、Angular轮番登场组件库多到挑花眼谁还会去关注一个基于jQuery的老牌UI框架但现实是你去翻一些企业内部系统、传统行业的管理后台、甚至某些还在稳定运行的ERP系统EasyUI的影子依然随处可见。我这次做EasyUI_简单登陆界面这个项目起因就是接手一个老项目的运维优化甲方明确要求界面风格保持原样但登录流程要重新做一遍。说白了EasyUI到现在还有生存空间核心原因就三个上手门槛极低、文档和示例足够老练、对老旧浏览器的兼容性比现代框架舒服太多。一个包含布局、表单、弹窗、表格、树形菜单的完整后台界面用EasyUI可以在一两天内拼出来这对很多业务驱动的项目来说是实打实的效率。登录页作为整个系统的门户正好适合用来展示EasyUI的典型用法组件加载、表单校验、异步交互、页面跳转几乎覆盖了一个前端页面最常见的所有需求。我必须先把话说清楚这不代表我建议新项目无脑选EasyUI。如果你的团队从零起步、没有历史包袱、对交互体验有较高要求那Vue或React搭配现成的组件库依然是更合理的选择。但如果你恰好遇到我这种情况——维护老项目、接手历史代码、或者需要一个几天内就能交付的内部系统原型——那么掌握EasyUI会让你在解决问题的路上顺很多。这篇博文围绕EasyUI_简单登陆界面这个打包项目展开我会把登录页从搭建到交付的完整过程拆开讲包括界面布局的取舍、表单校验的配置、登录请求的交互细节以及我实际踩过的几个坑。2. 登录页搭建前我做的三件事选版本、定结构、备素材2.1 版本选择EasyUI 1.9.4搭配jQuery 3.x最省心很多新手一上来就卡在第一步到底用哪个版本的EasyUI这个选择直接影响后续开发效率真不是随便打个最新版标签就完事。EasyUI目前官方最新版本是1.10.x系列但我工作这么久用得最顺手、资料最全、踩坑经验最丰富的其实是1.9.4版本。原因很简单1.9.4之后EasyUI主要在做修补性更新对普通业务开发来说功能差异不大但1.9.4的社区讨论量最大遇到问题搜索解决方案最容易命中。jQuery版本就更有讲究了。EasyUI 1.9.4官方推荐搭配jQuery 1.11.x但实际项目里我习惯直接用jQuery 3.4.1以上的版本。因为EasyUI核心是对DOM的操作和样式控制对jQuery新版本的API变动并不敏感用3.x版本兼容性没出过问题反而在处理一些现代浏览器的事件绑定上更顺滑。不过千万要注意别在EasyUI项目里混入jQuery 4.x这类测试版本稳定性优先。我最终采用的组合是jQuery 3.6.0 EasyUI 1.9.4 EasyUI中文语言包。这三个文件放在项目静态目录的lib文件夹下结构大概是lib/ ├── jquery.min.js ├── easyui/ │ ├── jquery.easyui.min.js │ ├── easyui-lang-zh_CN.js │ ├── themes/ │ │ ├── default/ │ │ ├── bootstrap/ │ │ └── icon.css │ └── plugins/这里多说一句中文语言包。EasyUI默认的语言包是英文界面虽然登录页本身文字可以自己写死中文但后续要做数据表格的分页、弹窗按钮的文字没有中文包会非常别扭。必须在页面引入JS之前提前加载语言包这个顺序错了会导致语言包完全不生效。2.2 布局设计居中卡片式登录比传统左右分栏更省事登录页的界面布局行业内大概有几种主流做法左右分栏的品牌区表单区结构、上下分栏的公司Logo表单结构、以及居中卡片式纯表单结构。EasyUI最常见的登录页模板是左右分栏左边放产品宣传图或者系统名称右边放登录表单。这种布局视觉冲击力强适合对外宣传属性的产品。但我这次做的是内部系统门户用户群体固定、目的明确不需要那么多品牌渲染所以我选了居中卡片式布局。居中卡片式的核心优势是适配性。不管用户屏幕是1366的办公本还是1920的显示器甚至某些还在用1024分辨率的旧电脑居中布局都不容易出问题。我用EasyUI实现这种布局的思路不算复杂整个body区域通过CSS实现水平垂直居中内部放一个宽420px左右的白色圆角卡片卡片内放系统Logo区域、登录标题、账号输入框、密码输入框、登录按钮。EasyUI负责的是输入框和按钮的样式加载整体页面框架还是我自己控制的。底色的选择对最终观感影响很大。我试过几种配色方案纯白背景显得太素深灰蓝背景配白卡片是当年后台系统的主流审美渐变背景则容易让整个页面显得花哨。最后定的是#2d3e50这类深蓝灰色做页面底色配白色卡片登录按钮用EasyUI默认主题里的蓝色系。这套配色在视觉上中规中矩但胜在耐看不会出现设计方案很好但落地后很怪的问题。2.3 必备资源字体图标、背景纹理和公司Logo位写登录页之前最好把资源位提前规划好否则写代码过程中来回补素材很打断思路。我的素材清单一般是这样系统Logo图放在卡片顶部居中位置尺寸建议60x60像素透明底PNG格式最稳妥登录按钮图标和输入框前缀图标EasyUI自带的icon.css里已经内置了基础图标集登录按钮用icon-lock或icon-key都行输入框前缀可以用icon-man和icon-lock这些不需要额外引入资源背景辅助纹理如果觉得纯色背景太单调可以用一张半透明的几何纹理图做背景叠加在底色上面避免登录页看起来空洞字体图标这一块EasyUI原生的图标集数量有限风格也偏老式桌面软件的感觉。如果对现代感有要求可以在项目中引入Font Awesome之类的第三方图标库然后通过CSS覆盖EasyUI的图标类名。但这次项目没做这一步内部系统追求的是稳定统一原生图标完全够用。3. 登录表单的实现细节EasyUI组件如何搭建用户输入区3.1 使用textbox组件构建账号和密码输入框EasyUI的输入框基础组件叫textbox它不是一个简单的input元素而是封装了一套包括外框、图标、清空按钮、校验状态在内的完整交互层。原生input标签在字体、边框、焦点状态上不同浏览器渲染细节不一样textbox则统一了这些表现。账号输入框的写法还是比较直观的。在HTML中放一个input加上EasyUI的class标识和data-options配置input idusername classeasyui-textbox stylewidth:100%;height:38px; >$.extend($.fn.validatebox.defaults.rules, { loginName: { validator: function(value) { return /^[a-zA-Z0-9_\u4e00-\u9fa5]{2,20}$/.test(value); }, message: 用户名为2-20位字母、数字、下划线或中文 }, pwdNotWeak: { validator: function(value) { return value.length 6; }, message: 密码长度不能少于6位 } });注册自定义规则后在data-options里把validType指定成自定义规则名即可。规则定义的关键在于validator方法返回Boolean值返回true表示校验通过false则会在输入框下方弹出message里的提示文字。这个机制看起来简单但实际开发中非常灵活常规的格式校验、长度校验、甚至联动校验比如二次确认密码这种需要比较两个输入框值的场景都可以通过自定义规则实现。校验触发的时机也值得单独说说。EasyUI的validatebox默认在输入框失去焦点blur时触发校验输入过程中不做即时判断。这是合理的默认行为输入过程中的频繁校验反而会打扰用户。但我建议在点击登录按钮时主动调用一次全局表单校验方法form(validate)这样能保证所有规则在提交动作发生前被执行一遍而不是依赖用户逐个输入框去触发blur事件。3.3 登录按钮的两种状态提交中与可提交登录按钮在提交过程中要进入提交中状态这是很多初写登录页的同学容易忽略的。如果不做任何处理用户快速点击两次提交按钮前端可能会发出两个登录请求后端如果恰好没有做幂等处理就会创建出两个会话或者产生数据异常。EasyUI的linkbutton组件自带两个实用的方法disable和enable。提交时先把按钮禁用同时把按钮文字改成登录中...请求结束无论成功还是失败后再恢复按钮的可用状态。代码逻辑不复杂function doLogin() { // 先判断表单整体校验是否通过 var isValid $(#loginForm).form(validate); if (!isValid) { return; } // 禁用按钮防止重复提交 $(#loginBtn).linkbutton(disable); $(#loginBtn).linkbutton({ text: 登录中... }); // 这里发送Ajax请求回调里恢复按钮状态 }这个细节对用户体感的提升远超想象。没有禁用逻辑的登录页点击后页面毫无反馈用户会忍不住多点几下反而引发更多问题。加了这个状态切换后用户一看按钮变成登录中...就知道请求已经发出去了配合一个加载中的转圈图标EasyUI的progressbar或icon-loading都可以体验直接上升一个台阶。我这里用的是Ajax提交而非原生form表单提交原因是EasyUI的form组件虽然支持AjaxSubmit方式但登录页还有额外的跳转逻辑、错误提示逻辑手写jQuery的$.ajax请求控制起来更灵活。两种方案都能跑通但做复杂交互的时候直接操作Ajax请求更符合我个人的代码习惯可读性和可维护性都更好。4. 登录请求的交互链路Ajax提交、回调处理与跳转策略4.1 Ajax请求参数格式与ContentType选择登录请求的ContentType选择不同团队差距很大常见的有两种传统的application/x-www-form-urlencoded和目前更多接口采用的application/json。EasyUI的老项目里大多数后端接口是Java的SpringMVC或者Struts2这些框架对form-urlencoded格式支持最完善所以我在这个项目里选择了传统表单格式提交。对应到$.ajax方法里需要把data设置成对象形式让jQuery自动序列化。关键代码如下$.ajax({ url: /api/login, type: POST, dataType: json, data: { username: $(#username).val(), password: $(#password).val(), remember: $(#rememberMe).is(:checked) ? 1 : 0 }, success: function(response) { // 处理登录结果 }, error: function(xhr, status, error) { // 处理网络错误 }, complete: function() { // 恢复按钮状态 } });这里有个特别容易踩坑的点dataType的json只是告诉jQuery把响应体按JSON来解析它不会自动帮你把请求体转成JSON格式。如果你需要在请求体里发送真正的JSON字符串必须在data里传入JSON.stringify后的字符串同时设置contentType为application/json。我见过不止一个同事在这里搞混结果后端接收到的是keyvaluekey2value2格式的字符串直接解析失败报参数错误。另一个必须处理的问题是Ajax超时。内部系统的网络环境相对稳定但也难免有服务端压力大、响应缓慢的时候。$.ajax默认没有超时时间请求挂起时用户看到登录中...可能会一直转圈。设置timeout: 1000010秒超时配合error回调里的超时判断可以让用户尽快感知到问题而不是在焦虑中等待。判断超时的方式是看error回调的error参数是否为timeout字符串。4.2 成功回调与失败回调的分支设计后端返回的登录结果我要求接口统一按下面的JSON结构返回{ code: 0, message: 登录成功, data: { token: xxx, username: admin, realName: 管理员 } }code为0表示成功非0则用message字段传递失败原因。这种设计的好处是前端处理逻辑异常清晰只判断code值成功走成功分支失败走失败分支不用为每种错误情况单独写判断逻辑。成功分支的处理相对简单保存返回的token到本地存储然后执行页面跳转。跳转这里我要特别强调一下老项目的特殊性。很多内部系统的登录页是放在iframe框架里的登录成功后如果只跳转当前iframe的页面用户会看到一个内容区缩在整站框架里的裸页面地址栏依然是登录页的地址刷新后还会回到登录页。正确做法是用JavaScript判断当前页面是否处于iframe环境中如果是需要跳转顶层窗口if (window.top ! window.self) { window.top.location.href /index.html; } else { window.location.href /index.html; }这段代码在开发和部署时都要实测。开发环境下登录页作为独立页面访问window.top和window.self通常是同一个对象但一旦部署到生产环境、页面被iframe嵌入两者的行为就会完全不同。我这次就是在部署后发现跳转地址对了但页面始终嵌在框架里排查了半天才发现问题出在这个iframe判断上。失败分支的设计比很多人想象的要复杂一点。后端返回的失败原因要区分展示给用户的业务错误比如用户名或密码错误和系统内部错误比如服务端异常请稍后再试。这两类信息的提示方式也不一样业务错误直接在登录卡片里用红色文字提示即可用户据此修正输入系统错误则建议用弹窗EasyUI的messager.alert提示因为这类错误不是用户能解决的弹窗能让用户意识到是系统侧问题而不是自己输入的问题。message字段里还有个细节要注意后端返回的message可能包含HTML标签或特殊符号如果不对内容做转义直接插入到DOM中存在XSS注入风险。虽然是内部系统但这个安全习惯必须有。最简单的做法是用text()方法而不是html()方法填充提示文案。4.3 记住密码功能的简单实现登录页上记住密码复选框是我额外加的一个功能内部系统用户每天要登录好多次这个功能对提升使用体验有实际帮助。由于内部系统的安全性要求不会像银行那样严格我采用了localStorage存储的方案而不是更复杂的Cookie方案。存储逻辑是这样的用户勾选记住密码并登录成功后把用户名和密码用Base64编码后存到localStorage下次用户打开登录页时先读取localStorage如果存在则自动填充账号密码并勾选记住密码复选框。用户取消勾选并登录时清除localStorage中的记录。// 读取 var saved localStorage.getItem(loginInfo); if (saved) { var info JSON.parse(saved); $(#username).textbox(setValue, decodeURIComponent(escape(atob(info.username)))); $(#password).textbox(setValue, decodeURIComponent(escape(atob(info.password)))); $(#rememberMe).prop(checked, true); } // 保存 if ($(#rememberMe).is(:checked)) { var info { username: btoa(unescape(encodeURIComponent($(#username).val()))), password: btoa(unescape(encodeURIComponent($(#password).val()))) }; localStorage.setItem(loginInfo, JSON.stringify(info)); } else { localStorage.removeItem(loginInfo); }这个方案在实现上存在一定的密码泄露风险毕竟Base64不是加密只能算编码。但如果你的项目是普通的内部管理系统、不涉及金融级别数据这个方案在便捷性和安全性之间能找到个平衡点。如果真的对安全有极致要求那就别做记住密码功能或者改用HTTPS Cookie的HttpOnly方案避免密码出现在前端存储中。5. 打包交付环节的常见坑版本混用、主题定制与跨页面问题5.1 CSS和JS的加载顺序不能错EasyUI项目里有一个薛定谔的bug代码逻辑全对但页面样式错乱、组件渲染不出来。这类问题九成以上出在引入顺序上。EasyUI的CSS必须在JS之前加载否则组件渲染时拿不到样式定义页面会出现裸奔的输入框——有EasyUI的DOM结构但没有任何样式效果。正确的引入顺序是先引jQuery再引EasyUI的CSS再引EasyUI的JS最后引中文语言包。语言包必须在EasyUI主JS之后引入因为它依赖EasyUI已经挂载到全局的对象。以下是该项目页面头部资源的完整顺序link relstylesheet typetext/css hreflib/easyui/themes/default/easyui.css link relstylesheet typetext/css hreflib/easyui/themes/icon.css script typetext/javascript srclib/jquery.min.js/script script typetext/javascript srclib/easyui/jquery.easyui.min.js/script script typetext/javascript srclib/easyui/easyui-lang-zh_CN.js/script还有一个偏门但很实际的坑如果你在页面里同时引了多个CSS主题文件后引入的会覆盖先引入的但覆盖规则并不完全可预测特别是涉及具体组件样式时。解决办法就是主题文件只保留一个千万别为了方便切换主题一次性引多个出现问题排查成本极高。5.2 主题定制主色改动只要动一个CSS变量文件登录页整体风格如果想要和公司品牌色一致EasyUI也支持主题定制。EasyUI 1.9.4的主题机制是把每个组件的颜色、边框、圆角等定义在对应的CSS类中默认主题存放在themes/default/easyui.css里。直接修改这个文件不推荐因为升级或覆盖时会丢失改动。正确做法是新建一个custom.css文件用更高优先级的选择器覆盖默认样式。比如我想把登录按钮从默认的蓝色改成品牌绿色就这么写.l-btn { background: #2e8b57 !important; border-color: #2e8b57 !important; color: #fff !important; }不过我这次项目没有大改主题色。内部系统的用户对颜色不敏感维持EasyUI默认的蓝色系反而能降低用户的学习成本毕竟他们已经习惯了老系统的视觉风格。把精力花在真正的功能逻辑上比反复调按钮颜色有意义得多。如果确实需要做品牌化定制比较简单快捷的方式是使用EasyUI官方提供的主题生成器这比手写CSS覆盖效率高很多。它会输出一份完整可替换的easyui.css文件直接覆盖即可。需要注意的是生成的CSS文件和当前版本必须匹配否则可能出现组件样式错乱的情况。5.3 浏览器兼容性实测与常见异常我在交付前对登录页做了跨浏览器实测覆盖了Chrome 120、Edge、Firefox、以及一台老电脑上的IE 11兼容模式。EasyUI官方宣称支持IE8以上但真实场景里IE 11对jQuery 3.x和部分ES6语法的支持都有局限。不过由于登录页代码我用的是ES5语法var声明、普通函数IE 11下跑通没有遇到问题。Chrome和Edge下的表现完全一致Firefox也没有明显差异。唯一要注意的是登录跳转后如果目标页面也依赖EasyUI组件目标页面也需要完整引入EasyUI资源文件不能假设登录页引入的资源会在跳转后继续生效。页面与页面之间的JS变量是完全隔离的除非你用window级全局变量传递数据否则跳转后刷新就什么都没了。本地开发调试登录页还有一个常见的坑用file://协议直接打开HTML时$.ajax请求会因为浏览器跨域策略直接失败。必须在本地起一个HTTP服务来访问最简单的办法是用Python或Node起个静态服务器或者用VSCode的Live Server插件。这个坑遇到的人非常多明明代码没问题、控制台却报跨域错误十有八九就是file协议打开的。6. 交付后我收藏的几条实战心得这个EasyUI登录页从开始到交付整体用时大概一个工作日。花的时间不算多但过程中几个细节给我的印象特别深写在这里算是对自己经验库的一次沉淀。第一登录页虽小却是整个系统里用户打开的第一个页面它的稳定性和响应速度直接影响用户第一印象。EasyUI的组件渲染依赖jQuery执行登录页加载时要确保JS脚本放在文档底部或使用DOMContentLoaded包装避免组件还没初始化用户就开始操作导致事件绑定失效。第二EasyUI生态的资料确实老旧大部分教程还停留在2015年以前。但好在它的API变动不大老资料里的写法搬到新版本上依然能用。遇到问题时与其在搜索引擎里大海捞针不如直接去官网看示例代码EasyUI官方的demo库是最权威的参考。第三也是我觉得最有价值的一条经验接手老项目时不要急着推翻重写。这个登录页原本用的是纯HTML原生JS功能能用但维护成本高界面也不符合现有系统风格。我用EasyUI重新实现一遍没有引入任何新框架接手的同事看到代码也不会陌生。在历史项目的技术栈里做局部优化往往比推倒重来更务实、风险更可控。如果你也在做一个类似的内部系统登录页希望这篇实战记录能帮你少走点弯路。EasyUI这套东西说不上先进但它在特定场景下的价值一直存在。关键在于你得明白自己为什么选它以及它在你这个项目里到底解决了什么问题。本文还有配套的精品资源点击获取
返回列表